代码生成工具jdbc+freemarker+swing
前言
公司比较小,为了节约成本,所以在领导授意下做了这个。
相对现在存在的各种自动生成框架来说,自己做的用起来更舒服一点,想怎么改就这么改。
什么前端 android什么的都能用到。
好吧 是领导叫我写技术文档的 但是不想碰word
工具采用jdbc连接数据库,freemarker作为输出模板,swing做界面操作。
效果
准备
面向过程的解释:
1.swing生成一个网格界面 ,读取配置为输入框赋值
2.用户填写配置进入界面 点击生成按钮
3.事件监听生效,并保存用户本次配置
4.根据用户配置调用不同模板配置
5.连接数据库 查询表和列信息
6.通过模板配置,获取到页面模板
7.通过freemarker生成模板并输出
8.通过开发工具 导出为jar(或者可运行jar都可以)
9.……下载exe4J……
10.根据官方文档或者软件提示 将jar转换成exe 软件中可以将jre一起打包 以免用户电脑没有安装java环境
<!-- 页面模板 --><dependency><groupId>freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.9</version></dependency><!-- 可以省下get set toString等代码--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.0</version><scope>provided</scope></dependency><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency><!-- 基本工具 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.7</version></dependency>
数据库
首先准备2个类接收数据库表和列的信息
1.表信息
package com.tnzt.config.generator.core.entity;import java.util.Date;
import java.util.List;import com.tnzt.config.generator.core.util.StringHelper;import lombok.Data;/*** @author zth*/
//lombok注解
@Data
public class Table {private String tableName;//表名称private String tableComment;//表描述//生成辅助private String path;//路径private String entityName;//实体名称private String entityFirstLowerName;private String daoName;//daoprivate String daoFirstLowerName;private String serviceName;//serviceprivate String serviceFirstLowerName;private String formName;//表单名称private String mapperName;//mapperprivate String actionName;//actionprivate String apiName;//接口private String apiUserName;//用户权限接口private String daoPackageName;//dao包名private String entityPackageName;//entityprivate String formPackageName;//表单private String mapperPackageName;//mapperprivate String servicePackageName;//serviceprivate String actionPackageName;//actionprivate String apiPackageName;//接口private String apiUserPackageName;//用户权限接口private String pagePackageName;//页面private String actionRequestMapping;//action请求地址private String apiRequestMapping;//接口请地址private Date genDateTime = new Date();private List<Column> columns = null;//字段列表private Column primaryColumn;//主键列表//设置列信息public void setColumns(List<Column> columns) {this.columns = columns;for(Column c:columns){if(c.getPrimary()==1){setPrimaryColumn(c);}}}//设置各种路径,freemarker模板中用到public void setDefault(Config config){if(tableName==null||tableName.equals("")){return ;}String[] tableNameArry = StringHelper.getSplit(tableName,config.getSplitFlag());path = "";if(tableNameArry.length>1){for(int i=1;i<tableNameArry.length;i++){if(i==1){entityName=StringHelper.firstToUpper(tableNameArry[i]);} else {entityName+=StringHelper.firstToUpper(tableNameArry[i]);}}path="."+tableNameArry[0];} else{entityName=StringHelper.firstToUpper(tableName);}entityFirstLowerName=StringHelper.firstToLower(entityName);daoName=entityName+config.getDaoName();daoFirstLowerName=StringHelper.firstToLower(daoName);serviceName=entityName+config.getServiceName();serviceFirstLowerName=StringHelper.firstToLower(serviceName);mapperName=entityName+config.getMapperName();actionName=entityName+config.getActionName();apiName=entityName+config.getApiName();apiUserName=entityName+config.getApiUserName();formName=entityName+config.getFormName();daoPackageName=config.getDaoPackageName()+path;entityPackageName=config.getEntityPackageName()+path;formPackageName=config.getFormPackageName()+path;servicePackageName=config.getServicePackageName()+path;mapperPackageName=config.getMapperPackageName()+path;actionPackageName=config.getActionPackageName()+path;apiPackageName=config.getActionPackageName()+".api"+path;apiUserPackageName=config.getActionPackageName()+".api.user"+path;pagePackageName="page";actionRequestMapping=path.replace(".", "/")+"/"+entityFirstLowerName+"/";apiRequestMapping=path.replace(".", "/")+"/api/"+entityFirstLowerName+"/";}}
2.列信息
package com.tnzt.config.generator.core.entity;import lombok.Data;/*** @author zth*/
@Data
public class Column {//字段名private String name;//首字母大写字段名private String nameTopBig;//数据库中得字段名private String dbName;//db字段类型private String dbType;//javaBean字段类型private String javaType;//javaBean字段类型private String jdbcType;//字段注释private String comment;//是否主键 0不是1是主键private int primary;}
3 .查询sql
package com.tnzt.config.generator.core.util;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;import com.tnzt.config.generator.core.entity.Column;
import com.tnzt.config.generator.core.entity.Config;
import com.tnzt.config.generator.core.entity.Table;/*** @author zth**/
public class DbHelper {/*** 根据表名获得字段名和注释列表* @param tableName* @return*/public static List<Column> getTableColumns(String tableName,Config config,Connection conn){//根据表名获得字段名和注释列表String sql = "select COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,COLUMN_KEY from information_schema.columns where table_name = ? and TABLE_SCHEMA = ?";PreparedStatement ppst = null;List<Column> columns = new ArrayList<Column>();Column column = null;boolean primaryFlag = false;int primaryNum = 0;try {//查询ppst = conn.prepareStatement(sql);ppst.setString(1, tableName);ppst.setString(2, config.getTableSchema());ResultSet rs = ppst.executeQuery();while(rs.next()){ column = new Column();column.setName(rs.getString("COLUMN_NAME"));column.setDbName(rs.getString("COLUMN_NAME"));column.setNameTopBig(StringHelper.firstToUpper(column.getName()));column.setDbType(rs.getString("DATA_TYPE"));if("PRI".equals(rs.getString("COLUMN_KEY"))){column.setPrimary(1);
// mc.setPrimaryColumn(column);primaryFlag = true;primaryNum++;}else{column.setPrimary(0);}//数字型if("int".equals(column.getDbType())){column.setJavaType("Integer");column.setJdbcType("INTEGER");}else if("bigint".equals(column.getDbType()) ){column.setJavaType("Long");column.setJdbcType("BIGINT");}else if("tinyint".equals(column.getDbType())){ column.setJavaType("Short");column.setJdbcType("TINYINT");}else if("smallint".equals(column.getDbType())){ column.setJavaType("Integer");column.setJdbcType("INTEGER");}else if("varchar".equals(column.getDbType())){column.setJavaType("String");column.setJdbcType("VARCHAR");}else if("text".equals(column.getDbType())){column.setJavaType("String");column.setJdbcType("LONGVARCHAR");}else if("char".equals(column.getDbType())){column.setJavaType("String");column.setJdbcType("CHAR");}else if("date".equals(column.getDbType()) || "time".equals(column.getDbType())){column.setJavaType("Date");column.setJdbcType("DATE");}else if("datetime".equals(column.getDbType()) ||"timestamp".equals(column.getDbType())){column.setJavaType("Date");column.setJdbcType("TIMESTAMP");}
// else if("datetime".equals(column.getDbType()) || "date".equals(column.getDbType()) || "time".equals(column.getDbType())){
// column.setJavaType("Date");
// column.setJdbcType("DATE");
// }else if("timestamp".equals(column.getDbType())){
// column.setJavaType("Date");
// column.setJdbcType("TIMESTAMP");
// }else if("decimal".equals(column.getDbType())){column.setJavaType("BigDecimal");column.setJdbcType("DECIMAL");}else if("float".equals(column.getDbType())){column.setJavaType("float");column.setJdbcType("FLOAT");}else{column.setJavaType(column.getDbType());column.setJdbcType(column.getDbType());}column.setComment(rs.getString("COLUMN_COMMENT")==null?"":rs.getString("COLUMN_COMMENT"));columns.add(column);} if(columns.size()<=0){System.out.println("["+tableName+"]是一个空表,没有任何字段");}if(!primaryFlag){System.out.println("["+tableName+"]表缺少主键");}else{if(primaryNum>1){System.out.println("["+tableName+"]表有["+primaryNum+"]个主键,生成工具暂时不能对多主键进行友好支持");}}rs.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return columns; }/*** 获取所有表名与表注释* @param config* @param conn* @return*/public static List<Table> getTableList(Config config,Connection conn){List<Table> tables=new ArrayList<Table>();String sql = "select table_name,table_comment from information_schema.tables where TABLE_SCHEMA = ? ";PreparedStatement ppst = null;try {ppst = conn.prepareStatement(sql);ppst.setString(1, config.getTableSchema());ResultSet rs = ppst.executeQuery();while(rs.next()){ Table table=new Table();table.setTableName(rs.getString("table_name"));table.setTableComment(rs.getString("table_comment"));tables.add(table);} rs.close();} catch (SQLException e) {e.printStackTrace();}return tables;}}
freemarker输出
下面是如何将数据库数据获得,并通过freemakrder模板输出
package com.tnzt.config.generator.core.util;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.apache.commons.lang3.StringUtils;import com.tnzt.config.generator.core.entity.Config;
import com.tnzt.config.generator.core.entity.Table;import freemarker.template.Template;/*** @author zth**/
public class EntityGenerator {//数据库驱动public static final String DBDRIVER = "com.mysql.jdbc.Driver";//模板包名public static String TEMPLATEPath = "com/config/freemarker/ssm";public void generator(Config config,String DBURL,String DBUSER,String DBPASS,int type) throws ClassNotFoundException, SQLException{//1、使用CLASS 类加载驱动程序 这玩意大家很熟悉吧 最早的无框架jdbc搞法Class.forName(DBDRIVER); Connection con = DriverManager.getConnection(DBURL,DBUSER,DBPASS); //2、连接数据库 if(con == null){return;}//获取表List<Table> tables=DbHelper.getTableList(config, con);for(Table table:tables){table.setDefault(config);//获取列table.setColumns(DbHelper.getTableColumns(table.getTableName(), config, con));//开始生成System.out.println("==========Entity生成==========");write(table,config,config.getEntityTemPateName(),table.getEntityPackageName(),table.getEntityName()+".java");System.out.println("==========Dao生成==========");write(table,config,config.getDaoTemPateName(),table.getDaoPackageName(),table.getDaoName()+".java");System.out.println("==========Service生成==========");write(table,config,config.getServiceTemPateName(),table.getServicePackageName(),table.getServiceName()+".java");System.out.println("==========Mapper生成==========");write(table,config,config.getMapperTemPateName(),table.getMapperPackageName(),table.getMapperName()+".xml");System.out.println("==========Form生成==========");write(table,config,config.getFormTemPateName(),table.getFormPackageName(),table.getFormName()+".java");System.out.println("==========Action生成==========");write(table,config,config.getActionTemPateName(),table.getActionPackageName(),table.getActionName()+".java");//页面生成 type 0:springboot 1:springmvcString viewDir="/"+config.getDefaultPackageName().replace(".", "_");viewDir = viewDir.substring(0,viewDir.length());String pageDir=viewDir+"/"+table.getPagePackageName()+"/"+table.getEntityFirstLowerName();switch (type) {case 1:System.out.println("==========Api生成==========");write(table,config,config.getApiTemPateName(),table.getApiPackageName(),table.getApiName()+".java");System.out.println("==========ApiUser生成==========");write(table,config,config.getApiUserTemPateName(),table.getApiUserPackageName(),table.getApiUserName()+".java");System.out.println("==========Page index.ftl生成==========");write(table,config,config.getIndexTemPateName(),pageDir,"index.html");System.out.println("==========Page build.ftl生成==========");write(table,config,config.getBuildTemPateName(),pageDir,"build.html");System.out.println("==========Page edit.ftl生成==========");write(table,config,config.getEditTemPateName(),pageDir,"edit.html");System.out.println("==========Page show.ftl生成==========");write(table,config,config.getShowTemPateName(),pageDir,"show.html");System.out.println("==========Page form.ftl生成==========");write(table,config,config.getPformTemPateName(),pageDir,"form.html");break;default:break;}}}/*** 写出代码文件* @param table* @param config* @param ftl* @param packageName* @param fileName*/private void write(Table table,Config config,String ftl,String packageName,String fileName){File file;if(StringUtils.isNotEmpty(table.getTableName())){String entityFolder=config.getSrcPath()+"/gcoder/"+packageName.replace(".", "/");String entityFile=entityFolder+"/"+fileName;file = new File(entityFolder);if(!file.exists()){file.mkdirs();}System.out.println("生成:"+entityFile);Map<String, Object> root = new HashMap<>();root.put("config", config);root.put("table", table);root.put("columns", table.getColumns());try {//freemarker写出loadContentByTemplate(config,root,ftl,entityFile);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}/*** freemarker模板写出* @param config* @param root* @param TemplateName* @param targetFile* @throws Exception*/@SuppressWarnings("deprecation")private void loadContentByTemplate(Config config,Map<String, Object> root,String TemplateName,String targetFile)throws Exception{InputStream is = null;BufferedReader br = null;Writer out = null;try {//加载freemarker模板文件//由于模板文件被打包在jar里面了 所有通过jvm加载 以流的方式读取模板is=this.getClass().getResourceAsStream(config.getTemplatePath()+TemplateName); br=new BufferedReader(new InputStreamReader(is,"UTF-8")); Template template = new Template(TemplateName, br);//如果模板文件放在jar包外面 则用路劲写出
// Template template = cfg.getTemplate(TemplateName); //输出模板out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), "UTF-8")); template.process(root,out);out.flush();} catch (IOException e) {e.printStackTrace();}finally {out.close();br.close();is.close();}}}
配置类相关
1.主配置类
package com.tnzt.config.generator.core.entity;import lombok.Data;/*** @author zth**/
@Data
public class Config {private String defaultPackageName;private String tableSchema;private String srcPath;private String templatePath;private String daoPackageName;//dao包名private String entityPackageName;//entity包名private String formPackageName;//form包名private String mapperPackageName;//mapper包名private String servicePackageName;//service包名private String actionPackageName;//action包名private String author="zth";private String version="v1.0.0";private String description="自动生成的代码";//路径生成配置private String splitFlag = "_";private String daoName = "Dao";//dao名称private String formName = "Form";//表单名称private String mapperName = "Mapper";//mapper名称private String serviceName = "ServiceBean";//service名称private String actionName = "Action";//Action名称private String apiName = "ApiAction";//Action名称private String apiUserName = "ApiUserAction";//Action名称private String defaultEntityPackageName = ".entity";//entity路径private String defaultDaoPackageName = ".dao";//dao路径private String defaultServicePackageName = "service";//service路径private String defaultMapperPackageName = ".mapper";//mapper路径private String defaultActionPackageName = ".action";//控制器路径private String defaultFormPackageName = ".form";//表单路径private String entityTemPateName = "entity.ftl";//entity模板名private String daoTemPateName = "dao.ftl";//dao模板名private String serviceTemPateName = "service.ftl";//service模板名private String mapperTemPateName = "mapper.ftl";//mapper模板名private String actionTemPateName = "action.ftl";//控制器模板名private String formTemPateName = "form.ftl";//表单模板名private String apiTemPateName = "api.ftl";//控制器模板名private String apiUserTemPateName = "api.ftl";//控制器模板名private String indexTemPateName = "index.ftl";//首页模板名private String buildTemPateName = "build.ftl";//新增页模板名private String editTemPateName = "edit.ftl";//编辑页模板名private String showTemPateName = "show.ftl";//详情页模板名private String pformTemPateName = "pform.ftl";//表单页模板名private String corePackageName = "com.tnzt.ssm.core.web.action";}
springboot配置类
package com.tnzt.config.generator.springboot;import com.tnzt.config.generator.core.entity.Config;import lombok.Data;
import lombok.EqualsAndHashCode;/*** @author zth**/
@Data
@EqualsAndHashCode(callSuper=false)
public class SpringBootConfig extends Config{private String TEMPTEMPLATEPath = "/com/tnzt/config/freemarker/springboot/";private String defaultPackageName;//默认包名private String daoName = "Mapper";//dao名称private String formName = "Form";//表单名称private String mapperName = "Mapper";//mapper名称private String serviceName = "Service";//service名称private String actionName = "Controller";//Action名称private String defaultEntityPackageName = ".entity";//dao路径private String defaultDaoPackageName = ".mapper";//dao路径private String defaultServicePackageName = ".services";//service路径private String defaultMapperPackageName = ".mapperdb";//mapper路径private String defaultActionPackageName = ".controllers";//控制器路径private String defaultFormPackageName = ".form";//表单路径private String actionTemPateName = "controller.ftl";public SpringBootConfig() { super.setTemplatePath(TEMPTEMPLATEPath);}public void setDefault(){setDefaultPackageName(defaultPackageName);setEntityPackageName(defaultPackageName+getDefaultEntityPackageName());setDaoPackageName(defaultPackageName+getDefaultDaoPackageName());setServicePackageName(defaultPackageName+getDefaultServicePackageName());setMapperPackageName(defaultPackageName+getDefaultMapperPackageName());setActionPackageName(defaultPackageName+getDefaultActionPackageName());setFormPackageName(defaultPackageName+getDefaultFormPackageName());super.setDaoName(daoName);super.setFormName(formName);super.setMapperName(mapperName);super.setServiceName(serviceName);super.setActionName(actionName);super.setActionTemPateName(actionTemPateName);}
}
springmvc+mybatis项目配置类 与springboot不同的地方也就是模板存放的目录 和一些模板的名称有变化而已
package com.tnzt.config.generator.ssm;import com.tnzt.config.generator.core.entity.Config;import lombok.Data;
import lombok.EqualsAndHashCode;/*** @author zth**/
@Data
@EqualsAndHashCode(callSuper=false)
public class SsmConfig extends Config{private String TEMPTEMPLATEPath = "/com/tnzt/config/freemarker/ssm/";private String defaultPackageName;//默认包名private String daoName = "Dao";//dao名称private String formName = "Form";//表单名称private String mapperName = "Mapper";//mapper名称private String serviceName = "Service";//service名称private String actionName = "Action";//Action名称private String apiName = "ApiAction";//api名称private String apiUserName = "ApiUserAction";//apiUser名称private String defaultEntityPackageName = ".entity";//dao路径private String defaultDaoPackageName = ".dao";//dao路径private String defaultServicePackageName = ".service";//service路径private String defaultMapperPackageName = ".mapper";//mapper路径private String defaultActionPackageName = ".action";//控制器路径private String defaultFormPackageName = ".form";//表单路径private String defaultApiActionPackageName = ".action.api";//api控制器路径private String defaultApiUserActionPackageName = ".action.api.user";//apiUser控制器路径public SsmConfig() { super.setTemplatePath(TEMPTEMPLATEPath);}public void setDefault(){setDefaultPackageName(defaultPackageName);setEntityPackageName(defaultPackageName+getDefaultEntityPackageName());setDaoPackageName(defaultPackageName+getDefaultDaoPackageName());setServicePackageName(defaultPackageName+getDefaultServicePackageName());setMapperPackageName(defaultPackageName+getDefaultMapperPackageName());setActionPackageName(defaultPackageName+getDefaultActionPackageName());setFormPackageName(defaultPackageName+getDefaultFormPackageName());super.setDaoName(daoName);super.setFormName(formName);super.setMapperName(mapperName);super.setServiceName(serviceName);super.setActionName(actionName);}
}
swing工具界面
其实上面的内容已经可以完成自动生成任务了 但是给人用的话 还需要稍微包装一下
界面生成
package com.tnzt.config.jframe;import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;import org.apache.commons.lang3.StringUtils;import com.tnzt.config.generator.core.entity.Config;
import com.tnzt.config.generator.core.util.EntityGenerator;
import com.tnzt.config.generator.core.util.PropertiesConfig;
import com.tnzt.config.thread.GpopConfigThread;/*** @author zth**/
public abstract class Jwindow extends JFrame implements ActionListener{private static final long serialVersionUID = 1L;//界面相关//界面提示文字组件private JLabel schma,address, userName, password,src,defaultPackage,gtype;//界面接收信息组件private JTextField textSchma,textAddress,textUserName, textUserPassword,textSrc,textDefaultPackage; //下拉框private JComboBox<String> comboboxGtype;//提交按钮private JButton submit;//网格界面布局器private GridBagLayout g = new GridBagLayout();//网格界面容器private GridBagConstraints c = new GridBagConstraints();//配置相关//配置文件 存放在当前用户的用户目录 用来保存上一次用的操作配置private Properties properties;//各个组件对应的properties中的key//哪个数据库private static String schma_key = "schma";//哪个ip地址private static String address_key = "address";//数据库账号private static String userName_key = "userName";//数据库密码private static String password_key = "password";//代码生成输出的文件路径private static String src_key = "src";//代码中默认的包名 如本文的 com.tnztprivate static String defaultPackage_key = "defaultPackage";//用哪个模板生成代码private static String gtype_key = "gtype";/*** 界面生成* @param str* @throws IOException*/public Jwindow(String str) throws IOException{super(str); //设置界面 宽 高setSize(350, 280); //用户单击窗口的关闭按钮时程序执行的操作setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置界面setLayout(g); //配置界面中的内容addComponent(); //加载配置loadConfig();}// 在这个方法中将会添加所有的组件; // 使用的网格包布局;希望楼主能看懂; @SuppressWarnings({ "unchecked", "rawtypes" })private void addComponent(){// 数据库名字schma = new JLabel("数据库名:"); add(g, c, schma, 0, 1, 1, 1); // 数据库名字输入textSchma = new JTextField("huilian",15);add(g, c, textSchma, 1, 1, 2, 1); // 数据库连接地址address = new JLabel("主机名或IP地址:"); add(g, c, address, 0, 2, 1, 1); // 数据库连接地址输入textAddress = new JTextField("10.7.13.48:8066",15); add(g, c, textAddress, 1, 2, 2, 1); // 用户名 userName = new JLabel("数据库用户名 :"); add(g, c, userName, 0, 3, 1, 1); // 用户名输入框 textUserName = new JTextField("huilian",15); add(g, c, textUserName, 1, 3, 2, 1); // 密码: password = new JLabel("数据库密码:"); add(g, c, password, 0, 4, 1, 1); // 密码输入框 textUserPassword = new JTextField("MLjmhddGBfdMHbdPkKhbd",15); add(g, c, textUserPassword, 1, 4, 2, 1); // 目标路径: src = new JLabel("目标路径:"); add(g, c, src, 0, 5, 1, 1); // 目标路径入框 textSrc = new JTextField("D:/",15); add(g, c, textSrc, 1, 5, 2, 1); // 默认包名: defaultPackage = new JLabel("默认包名:"); add(g, c, defaultPackage, 0, 6, 1, 1); // 默认包名入框 textDefaultPackage = new JTextField("tf56.huilian",15); add(g, c, textDefaultPackage, 1, 6, 2, 1); // 框架: gtype = new JLabel("生成框架:"); add(g, c, gtype, 0, 7, 1, 1); // 框架下拉列表 comboboxGtype = new JComboBox(); comboboxGtype.addItem("springboot");comboboxGtype.addItem("ssm");add(g, c, comboboxGtype, 1, 7, 2, 1);// submit按钮submit = new JButton("快速生成");c.insets = new Insets(8, 0, 4, 0);add(g, c, submit, 1, 8, 1, 1);submit.addActionListener(this); setVisible(true); setLocationRelativeTo(null);// 设居中显示;}private void add(GridBagLayout g, GridBagConstraints c, JComponent jc,int x, int y, int gw, int gh){c.gridx = x;c.gridy = y;c.anchor = GridBagConstraints.WEST;c.gridwidth = gw;c.gridheight = gh;g.setConstraints(jc, c);add(jc);}private void loadConfig() throws IOException {properties = PropertiesConfig.loadProperties();//定义并设置数据if(properties.isEmpty()) {return;}String schma_value = properties.getProperty(schma_key);if(StringUtils.isNotBlank(schma_value)) {textSchma.setText(schma_value);}String address_value = properties.getProperty(address_key);if(StringUtils.isNotBlank(address_value)) {textAddress.setText(address_value);}String userName = properties.getProperty(userName_key);if(StringUtils.isNotBlank(userName)) {textUserName.setText(userName);}String password_value = properties.getProperty(password_key);if(StringUtils.isNotBlank(password_value)) {textUserPassword.setText(password_value);}String src_value = properties.getProperty(src_key);if(StringUtils.isNotBlank(src_value)) {textSrc.setText(src_value);}String defaultPackage_value = properties.getProperty(defaultPackage_key);if(StringUtils.isNotBlank(defaultPackage_value)) {textDefaultPackage.setText(defaultPackage_value);}String gtype_value = properties.getProperty(gtype_key);if(StringUtils.isNotBlank(gtype_value)) {comboboxGtype.setSelectedIndex(Integer.parseInt(gtype_value));}}/** * 用户操作监听(点了生成按钮)*/@Overridepublic void actionPerformed(ActionEvent event) {//各种数据取出来String DBUSER = textUserName.getText();String DBPASS = textUserPassword.getText();String SRCPath = textSrc.getText();String TABLE_SCHEMA=textSchma.getText();String DEFAULT_PACKAGE=textDefaultPackage.getText();String DBURL= "jdbc:mysql://"+textAddress.getText()+"/"+TABLE_SCHEMA+"?characterEncoding=utf8";int type = comboboxGtype.getSelectedIndex();Map<String, Object> map = new HashMap<String, Object>();map.put(schma_key, TABLE_SCHEMA);map.put(address_key, textAddress.getText());map.put(userName_key, DBUSER);map.put(password_key, DBPASS);map.put(src_key, SRCPath);map.put(defaultPackage_key, DEFAULT_PACKAGE);map.put(gtype_key, type);try {//开启线程保存用的操作配置 GpopConfigThread t = new GpopConfigThread(map);new Thread(t).start();;//根据获取的用户设置建立相关配置Config config = buildConfig(DEFAULT_PACKAGE, SRCPath, TABLE_SCHEMA,type);if(config == null) {JOptionPane.showMessageDialog(null, "请选择模板类型", "提示", 0);}//执行生成代码EntityGenerator e = new EntityGenerator();e.generator(config,DBURL,DBUSER,DBPASS,type);JOptionPane.showMessageDialog(null, "自动生成成功---->"+SRCPath+"/gcoder", "提示", 1);} catch (Exception e) {e.printStackTrace();JOptionPane.showMessageDialog(null, e.getMessage(), "提示", 0);}}/*** 建立相关配置* @param DEFAULT_PACKAGE* @param SRCPath* @param TABLE_SCHEMA* @param type* @return*/public abstract Config buildConfig(String DEFAULT_PACKAGE,String SRCPath,String TABLE_SCHEMA,int type);}
配置文件相关
package com.tnzt.config.generator.core.util;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;/*** @author zth**/
public class PropertiesConfig{//配置保存的目录private static String config_dir = "gcoder";//配置文件名称private static String config_name = "gcoder.propertise";//获取当前用户目录private static String config_dir_path = System.getProperty("user.home")+File.separator+config_dir;//文件路径private static String config_path = config_dir_path+File.separator+config_name;/*** 保存设置* @param pops* @throws IOException*/public static void setConfig(Map<String, Object> pops) throws IOException { FileOutputStream fout = null;try { fout = new FileOutputStream(config_path);Properties properties = new Properties();Iterator<String> i = pops.keySet().iterator();while (i.hasNext()) {String key = i.next();Object value = pops.get(key);if(value ==null) {continue;}properties.setProperty(key, String.valueOf(value));}properties.store(fout, null); } catch (IOException e) { e.printStackTrace(); }finally {fout.close(); }} /*** 读取设置* @return* @throws IOException*/public static Properties loadProperties() throws IOException {FileInputStream fin = null;Properties properties = null;try {properties = new Properties();File f = new File(config_path);if(!f.exists()) {File dir = new File(config_dir_path);dir.mkdirs();f.createNewFile();}fin = new FileInputStream(f);properties.load(fin);} catch (Exception e) {e.printStackTrace();}finally {fin.close();}return properties;}
}
配置保存线程
package com.tnzt.config.thread;import java.io.IOException;
import java.util.Map;import com.tnzt.config.generator.core.util.PropertiesConfig;/*** @author zth**/
public class GpopConfigThread implements Runnable{private Map<String, Object> params;public GpopConfigThread(Map<String, Object> params) {this.params = params;}@Overridepublic void run() {try {PropertiesConfig.setConfig(params);} catch (IOException e) {e.printStackTrace();}}}
主运行类(可运行jar的main方法)
package com.tnzt.config.main;import java.io.IOException;import com.tnzt.config.generator.core.entity.Config;
import com.tnzt.config.generator.springboot.SpringBootConfig;
import com.tnzt.config.generator.ssm.SsmConfig;
import com.tnzt.config.jframe.Jwindow;/*** @author zth**/
public class MainProcessor extends Jwindow{private static final long serialVersionUID = 1L;public MainProcessor(String str) throws IOException {super(str);}@Overridepublic Config buildConfig(String DEFAULT_PACKAGE, String SRCPath, String TABLE_SCHEMA, int type) {switch (type) {case 0:SpringBootConfig springBootConfig=new SpringBootConfig();springBootConfig.setDefaultPackageName(DEFAULT_PACKAGE);springBootConfig.setDefault();springBootConfig.setSrcPath(SRCPath);springBootConfig.setTableSchema(TABLE_SCHEMA);return springBootConfig;case 1:SsmConfig ssmConfig=new SsmConfig();ssmConfig.setDefaultPackageName(DEFAULT_PACKAGE);ssmConfig.setDefault();ssmConfig.setSrcPath(SRCPath);ssmConfig.setTableSchema(TABLE_SCHEMA);return ssmConfig;default:return null;}}public static void main(String[] args) throws IOException {new MainProcessor("代码自动生成工具");}}
相关的一些工具类
package com.tnzt.config.generator.core.util;import org.apache.commons.lang3.StringUtils;/*** @author zth**/
public class StringHelper {/*** 分割字符串* @param splitStr* @param splitFlag* @return*/public static String[] getSplit(String splitStr,String splitFlag){return splitStr.split(splitFlag);}/**首字母大写* @param str* @return*/public static String firstToUpper(String str){if(StringUtils.isBlank(str)) {return str;}return str.substring(0, 1).toUpperCase()+str.substring(1);}/**首字母小写* @param str* @return*/public static String firstToLower(String str){if(StringUtils.isBlank(str)) {return str;}return str.substring(0, 1).toLowerCase()+str.substring(1);}
}
freemarker模板写法
因为是模板嘛 不和任何语言挂钩 所以生成java文件 html页面 什么的都可以
这个下面贴几个有代表性的的模板
action类
package ${table.actionPackageName};import ${table.servicePackageName}.${table.serviceName};
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ${table.entityPackageName}.${table.entityName};
import tf56.ehuodi.domain.ResultPojo;
import tf56.ehuodi.utils.RequestUtils;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import tf56.ehuodiOperate.utils.NumberUtils;
import tf56.huilian.services.LockService;/*** ${table.actionName}* ${table.tableComment}* @author ${config.author}* @version ${config.version}* 描述:${config.description}* 时间:${table.genDateTime?string("yyyy-MM-dd HH:mm:ss")}*/
@RestController
@RequestMapping("${table.actionRequestMapping}")
public class ${table.actionName}{private static final Logger LOGGER = LoggerFactory.getLogger(${table.actionName}.class);private static String insert_lock_key = "${table.actionName}_lock_insert${table.entityName}";@Autowiredprivate LockService lockService;@Autowiredprivate ${table.serviceName} ${table.serviceFirstLowerName};/******************************开发的代码区域 开始***************************//******************************开发的代码区域 结束***************************//***************************自动生成的代码区域 开始**************************/<#assign num=0 /><#list columns as column><#if column.name == 'updateJobcard' || column.name == 'updateUsername'><#assign num=num+1 /></#if></#list>/*** 新增 ${table.tableComment}* @param ${table.entityFirstLowerName}* @return*/@RequestMapping(value = "/insert",method= RequestMethod.POST)public String insert(HttpServletRequest req, @Valid ${table.entityName} ${table.entityFirstLowerName}) {LOGGER.info("新增 ${table.tableComment} 入参:{}",${table.entityFirstLowerName});if(${table.entityFirstLowerName}.get${table.primaryColumn.nameTopBig}()!=null){return ResultPojo.Err("id不可传入").toJson();}if (!lockService.lock(insert_lock_key)) {return ResultPojo.Err("当前已有操作进行中").toJson();}try{ResultPojo res = ${table.serviceFirstLowerName}.insert(${table.entityFirstLowerName});return res.toJson();}catch(Exception e){LOGGER.info("${table.tableComment} 新增 失败 :",e);return ResultPojo.Err("创建失败").toJson();}finally {lockService.unlock(insert_lock_key);}}/*** 删除 ${table.tableComment}* @param id* @return*/@RequestMapping(value = "/delete",method= RequestMethod.POST)public String delete(String ${table.primaryColumn.name}) {LOGGER.info("删除 ${table.tableComment} 入参:{}",${table.primaryColumn.name});ResultPojo res = ${table.serviceFirstLowerName}.delete(${table.primaryColumn.name});return res.toJson();}/*** 编辑 ${table.tableComment}* @param ${table.entityFirstLowerName}* @return*/@RequestMapping(value = "/update",method= RequestMethod.POST)public String update(HttpServletRequest req,@Valid ${table.entityName} ${table.entityFirstLowerName}) {LOGGER.info("修改 ${table.tableComment} 入参:{}",${table.entityFirstLowerName}); <#if num == 2>setUser(req,${table.entityFirstLowerName}); //写入 操作用户</#if>ResultPojo<Integer> res = ${table.serviceFirstLowerName}.update(${table.entityFirstLowerName});return res.toJson();}/*** 通用列表查询 ${table.tableComment}* @param HttpServletRequest* @return*/@RequestMapping(value = "/selectList",method= RequestMethod.POST)public String selectList(HttpServletRequest request) {Map<String, String> params = RequestUtils.getParamMapFromRequest(request);return ${table.serviceFirstLowerName}.selectList(params);}/*** 通用单体查询 ${table.tableComment}* @param ${table.primaryColumn.name}* @return*/@RequestMapping(value = "/selectOne",method= RequestMethod.POST)public String selectOne(String ${table.primaryColumn.name}) {return ${table.serviceFirstLowerName}.selectOne(${table.primaryColumn.name});}<#if num == 2>private void setUser(HttpServletRequest req,${table.entityName} ${table.entityFirstLowerName}){String username = (String) req.getParameter("username");String jobCard = (String) req.getParameter("jobCard");${table.entityFirstLowerName}.setUpdateJobcard(jobCard);${table.entityFirstLowerName}.setUpdateUsername(username);} </#if>/***************************自动生成的代码区域 结束**************************/}
dao里面就个类名和继承不需要内容就不贴了
贴个实体类的
package ${table.entityPackageName};
<#assign isDate=false isBigDecimal=false>
<#list columns as column><#if column.name!="id"&&column.name!="createdAt"&&column.name!="updatedAt"><#if column.javaType=="Date" && !isDate>
import java.util.Date;<#assign isDate=true></#if><#if column.javaType=="BigDecimal" && !isBigDecimal>
import java.math.BigDecimal;<#assign isBigDecimal=true></#if></#if>
</#list>
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;/*** ${table.tableComment}* @author ${config.author}* @version ${config.version}* 描述:${config.description}* @since ${table.genDateTime?string("yyyy-MM-dd HH:mm:ss")}*/
@Data
public class ${table.entityName}{<#list columns as column>//${column.comment}<#if column.javaType=="Date">@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")</#if>private ${column.javaType} ${column.name};</#list>}
mybatie 的 mapper 这个和实体dao其实 mybatis generator 插件也可以生成的
就看里面需要什么方法了
<?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" >
<!-- * ${table.mapperName}* ${table.tableComment}* @author ${config.author}* @version ${config.version}* 描述:${config.description}* 时间:${table.genDateTime?string("yyyy-MM-dd HH:mm:ss")}
-->
<mapper namespace="${table.daoPackageName}.${table.mapperName}" ><resultMap id="BaseResultMap" type="${table.entityPackageName}.${table.entityName}" > <#list columns as column><#if column.primary==1><id column="${column.dbName}" property="${column.name}" jdbcType="${column.jdbcType}" /><!--${column.comment}--></#if><#if column.primary==0><result column="${column.dbName}" property="${column.name}" jdbcType="${column.jdbcType}" /><!--${column.comment}--></#if></#list></resultMap><!--****************************开发的代码区域 开始****************************--><!--****************************开发的代码区域 结束****************************--><!--***************************自动生成的代码区域 开始**************************--><!-- 插入数据 --><insert id="insert" parameterType="${table.entityPackageName}.${table.entityName}"> insert into <include refid="table_name" /><trim prefix="(" suffix=")" suffixOverrides="," ><#list columns as column><#if column.dbName != 'createDate' && column.dbName != 'updateDate'&& column.dbName != 'stampDate'><if test="${column.name} != null" >${column.dbName},</if><#else>${column.dbName},</#if></#list></trim><trim prefix="values (" suffix=")" suffixOverrides="," ><#list columns as column><#if column.dbName != 'createDate' && column.dbName != 'updateDate'&& column.dbName != 'stampDate'><if test="${column.name} != null" >${'#'}${'{'}${column.name}${'}'},</if><#else>NOW(),</#if></#list></trim></insert><!-- 根据主键删除数据 --><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >delete from <include refid="table_name" /><include refid="primaryCondition"/> </delete><!-- 根据主键修改数据 --><update id="updateByPrimaryKeySelective" parameterType="${table.entityPackageName}.${table.entityName}" >update <include refid="table_name" /><set><#list columns as column><#if column.dbName != 'updateDate'&& column.dbName != 'stampDate'><if test="${column.name} != null" >${column.dbName} = ${'#'}${'{'}${column.name}${'}'},</if><#else>${column.dbName} = NOW(),</#if></#list></set><include refid="primaryCondition"/> </update><!-- 根据条件查询数量 --><select id="selectCountByCondition" resultType="java.lang.Integer" parameterType="java.util.Map" >selectcount(1)from <include refid="table_name" /><include refid="selectByCondition_where" /></select><select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >select<include refid="Base_Column_List" />from <include refid="table_name" /><include refid="primaryCondition"/> </select><select id="selectByCondition" resultMap="BaseResultMap" parameterType="java.util.Map" >select<include refid="Base_Column_List" />from <include refid="table_name" /><include refid="selectByCondition_where" /></select><!-- 以下引用sql --><!-- 表名 --><sql id="table_name">${table.tableName}</sql><!-- 主键条件 --><sql id="primaryCondition"><where>${table.primaryColumn.name} = ${'#'}${'{'}${table.primaryColumn.name}${'}'}</where></sql><!-- 全部列名 --><sql id="Base_Column_List" ><#list columns as column>${column.dbName}<#if column_has_next>,</#if></#list></sql><!-- 通用条件判断 --><sql id="selectByCondition_where"><where><#list columns as column><if test="${column.name}!=null"><#if column_index != 0> and </#if>${column.dbName} = ${'#'}{${column.name}}</if></#list></where><if test="orderBy!=null">order by ${r'#{orderBy}'}</if><if test="skipCount != null and pageSize != null">LIMIT ${r'#{skipCount}'}${r'#{pageSize}'}</if></sql><!--***************************自动生成的代码区域 结束**************************--></mapper>
service也没啥 就是调调基类的方法
最后搞个页面把
${r'<@c.header/>'}
<script type="text/javascript">$(function(){$("#searchBtn").click(function(){$("#searchForm").attr("action","${r'${request.contextPath}'}${table.actionRequestMapping}index.do");$("#searchForm").submit();});$("#createBtn").click(function(){$("#searchForm").attr("action","${r'${request.contextPath}'}${table.actionRequestMapping}build.do");$("#searchForm").submit();});$("#deleteBtn").click(function(){confirm("你确定要删除吗?","confirmTip",function(){if($("input[group='idGroup']:checked").length > 0){var array = new Array();$("input[group='idGroup']:checked").each(function(){array.push(this.value);});$("#searchForm").attr("action","${r'${request.contextPath}'}${table.actionRequestMapping}delete.do?ids="+array.toString());$("#searchForm").submit();}else{Alert('请选择要删除的数据!','alertTip');}});})}); <#list columns as column><#if column.name=="state">function stateUpdate(id,state){$("#searchForm").attr("action","${r'${request.contextPath}'}${table.actionRequestMapping}stateUpdate.do?id="+id+"&state="+state);$("#searchForm").submit();}</#if></#list>
</script>
<div class="admin-content"><div class="admin-biaogelist"><div class="listbiaoti am-cf contextposition"><dl class="am-icon-home topposition"> 当前位置:管理><a href="Javascript: void(0);">${table.tableComment}管理</a></dl></div> <form id="searchForm" name="searchForm" method="post"><input type="hidden" id="curPage" name="curPage" value="${r'${form.curPage}'} "><div class="am-g" id="form" ><div class="am-u-md-12 searchbuttondiv"><div class="am-btn-toolbars am-btn-toolbar am-kg am-cf serchbuttontoolbardiv"><ul><li><div class=""><button id="searchBtn" type="button" class="am-btn am-btn-secondary am-btn-md am-margin-right-sm am-margin-bottom-sm"><span class="am-icon-search"></span> 搜索</button>${r'<@shiro.hasPermission name="'}${table.entityName}${r':delete">'} <button id="deleteBtn" type="button" class="am-btn am-btn-warning am-btn-md am-margin-right-sm am-margin-bottom-sm"><span class="am-icon-trash"></span> 删除</button>${r'</@shiro.hasPermission>'}${r'<@shiro.hasPermission name="'}${table.entityName}${r':add">'} <button id="createBtn" type="button" class="am-btn am-btn-success am-btn-md am-margin-right-sm am-margin-bottom-sm"><span class="am-icon-plus"></span> 新 增</button>${r'</@shiro.hasPermission>'}</div></li></ul></div></div></div></form> <form class="am-form am-g" id="contextForm" name="contextForm"><table width="100%" id="headlocktable" class="am-table am-table-bordered am-table-radius am-table-striped am-table-hover am-text-center"><thead class="fixed-thead"><tr class="" class="index-table-head"><th class="table-check am-text-center contexttd"><input type="checkbox" οnclick="formcheckclick(this)"/></th><#list columns as column><#if column.name!="id"&&column.name!="createdAt"&&column.name!="updatedAt"&&column.comment?index_of("[imgs]")==-1&&column.comment?index_of("[richtextarea]")==-1><th class="table-title am-text-center contexttd">${column.comment?replace('[textarea]','')}<!--<a href="javascript:sort('${column.dbName}','${r'${sort}'}')">${column.comment}</a>--></th></#if></#list><th style="width:200px;" class="table-set am-text-center contexttd">操作</th> </tr> </thead><tbody class="scroll-tbody">${r'<#list page.data as obj>'}<tr><td class="table-check am-text-center contexttd"><input type="checkbox" group="idGroup" value="${r'${obj'}.id}"/></td><#list columns as column><#if column.name!="createdAt"&&column.name!="updatedAt"&&column.comment?index_of("[imgs]")==-1><#if column.javaType=="Date"><td class="table-title-id am-text-center contexttd">${r'${obj.'}${column.name}?datetime}</td><#elseif column.name=="id"><#elseif column.name=="state"><td class="table-title-id am-text-center contexttd">${r'${obj.state.desc}'}</td><#elseif column.comment?index_of("[img]")!=-1><td class="table-title am-text-center contexttd">${r'<#if obj.'}${column.name}${r'??>'}<img src='${r'${obj.'}${column.name}${r'Path}'}'/>${r'</#if>'}</td><#elseif column.comment?index_of("[richtextarea]")!=-1><#else> <td class="table-title-id am-text-center contexttd">${r'${obj.'}${column.name}}</td></#if></#if></#list><td class="am-text-center contexttd"><div class="am-btn-toolbar"><div class="am-btn-group am-btn-group-xs nofloat" >${r'<@shiro.hasPermission name="'}${table.entityName}${r':show">'}<button title="查看" class="am-btn am-btn-default am-btn-xs am-round" type="button" οnclick="javascript:showData(${r'${obj.id}'});"><a href="javascript:void(0);" ><span class="am-icon-search am-text-success"></span></a></button>${r'</@shiro.hasPermission>'}${r'<@shiro.hasPermission name="'}${table.entityName}${r':edit">'}<button title="修改" class="am-btn am-btn-default am-btn-xs am-round" type="button" οnclick="javascript:updateData(${r'${obj.id}'});"><a href="javascript:void(0);" ><span class="am-icon-edit am-text-secondary"></span></a></button>${r'</@shiro.hasPermission>'}${r'<@shiro.hasPermission name="'}${table.entityName}${r':delete">'} <button title="删除" class="am-btn am-btn-default am-btn-xs am-round" type="button" οnclick="javascript:deleteData(${r'${obj.id}'});"><a href="javascript:void(0);" ><span class="am-icon-trash am-text-warning"></span></a></button>${r'</@shiro.hasPermission>'}<#list columns as column><#if column.name=="state">${r'<@shiro.hasPermission name="'}${table.entityName}${r':edit">'}${r'<#if obj.state.value==0>'}<button title="启用" class="am-btn am-btn-default am-btn-xs am-round" type="button" οnclick="javascript:stateUpdate(${r'${obj.id}'},1);"><a href="javascript:void(0);" ><span class="am-icon-rocket am-text-secondary"></span></a></button>${r'<#else>'}<button title="禁用" class="am-btn am-btn-default am-btn-xs am-round" type="button" οnclick="javascript:stateUpdate(${r'${obj.id}'},0);"><a href="javascript:void(0);" ><span class="am-icon-ban am-text-secondary" style="color:gray"></span></a></button>${r'</#if>'}${r'</@shiro.hasPermission>'}</#if></#list></div></div></td></tr>${r'</#list>'}</tbody></table><div class="am-u-sm-7 am-u-md-7 am-u-lg-7 am-margin-bottom-sm tabletail"><p class="am-margin-top-sm am-margin-bottom-sm"><span class="remarktext"> 备注:操作图标含义</span><a class="am-icon-search remarkshow" title="查看"> 查看</a> <a class="am-icon-edit remarkedit" title="修改">修改</a> <a class="am-icon-trash remarkdelete" title="删除"> 删除</a> <#list columns as column><#if column.name=="state"><a class="am-icon-rocket" style="color:#0e90d2" title="启用"> 启用</a> <a class="am-icon-ban" style="color:gray" title="禁用"> 禁用</a> </#if></#list></p></div><div class="am-u-sm-5 am-u-md-5 am-u-lg-5 am-margin-bottom-sm tabletail">${r'<@c.pagination/>'}</div></form></div>
</div>
${r'<@c.footer/>'}
总结
萌新第一次发博客 应该会有很多错别字 而且排版也会不人道 请大家多多见谅
看文章的小伙伴 请尽量帮忙优化和去除繁杂代码 比如写出文件也可以开线程等
谢谢大家 希望能收到大家的建议
代码生成工具jdbc+freemarker+swing相关推荐
- 一款自定义模版的代码生成工具
codegen 一款自定义模版(freemarker)的代码生成工具 快速入门 clone代码 git clone git@github.com:YaoLin1/codegen.git 编译 在cod ...
- Hibernate代码生成工具 设计全攻略
1.简述Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了轻量级的对象封装,提供HQL查询语言,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库.使用Hibernat ...
- mybatis java8_Java 8 开发的 Mybatis 注解代码生成工具
MybatisAnnotationTools MybatisAnnotationTools 是基于 Java8 开发的一款可以用于自动化生成 MyBatis 注解类的工具,支持配置数据源.类路径,表名 ...
- 使用iBatis的自动化代码生成工具Abator
原来还不知道iBatis也有像Hibernate类似的自动化代码生成工具,今天找到Abator这工具也挺不错的,在ecelipse上面小试了一把: 1.获得Abator http://ibatis.a ...
- 支持自定义代码生成工具
项目地址 https://github.com/kylin-hunter/k-commons/tree/main/k-code-generator 文章目录 项目地址 前言 一.架构 二.使用步骤 1 ...
- ZeusAutoCode代码生成工具(开源)
ZeusAutoCode代码生成工具 一.简介 Zeus代码生成器是一款自动代码生成工具,旨在快速生成基础的CRUD代码,在此基础上也提供了一些高级功能,做到灵活配置,生成可扩展性强的代码. 后端是基 ...
- 狼奔代码生成工具使用心得
狼奔代码生成工具(http://ltfwan.d33140.jit8.cn)是一款为程序员设计的代码生成器,更是一款软件项目智能开发平台,它可以自动生成ASP.NET页面及后台代码,采用了面向服务的架 ...
- 调整代码生成工具Database2Sharp的Winform界面生成,使其易于列表工具栏的使用。...
在Winform界面开发的时候,有时候我们客户喜欢把功能放在列表界面的顶部,这样界面和功能整齐放置,也是一种比较美观的方式,基于这种方式的考虑,改造了代码生成工具的Winform界面生成规则,把增删改 ...
- CLR_via_C#.3rd 翻译[1.5 本地代码生成工具NGen.exe]
1.5 The Native Code Generator Tool: NGen.exe 本地代码生成工具NGen.exe NGen.exe是和.NET框架绑定在一起的.当用户的机器上安装了一个应用程 ...
最新文章
- 百度搜索引擎广告SEM调用架构示意图
- 如何调试Android Native Framework
- 下载python的步骤ios_下载及安装Python详细步骤
- Spring简单总结
- erlang精要(5)-列表推导式
- P5707 【深基2.例12】上学迟到(python3实现)
- 解决tomcat不支持中文路径的问题
- 用三国杀讲分布式算法,太舒适了吧?
- hdu 1232 经典并查集应用
- ADB与按键精灵手机助手连接手机调试问题记录
- C语言显示图书信息的讲解,C语言图书信息管理系统解析.pdf
- 自己用java写一个http和https代理服务器
- Java mail outlook发邮件提示升级TLS1.2
- 关于微信小程序自定义交易组件升级处理的相关问题,及解决思路
- Node.js Web 模块(客户端 服务端实例)
- “美国国家标准化组织(ANSI)”是一个核准多种行业标准的组织,我们可以把数据库看成这样一种有组织的机制
- Windows应急响应
- C语言实现埃拉托色尼筛选法(剔除数组中的非质数)
- S3DIS 点云数据集的手动修复问题
- PDF Search for Mac(PDF文件搜索工具)
热门文章
- C# 调用Windows media play 播放器方法
- 关于傅立叶系数的计算公式
- 使用系统打印服务器配置,打印服务器配置教程.pdf
- SilverLight合计行设计
- cube的意思中文翻译_cube是什么意思_cube的翻译_音标_读音_用法_例句_爱词霸在线词典...
- 数据结构—查找(顺序查找和折半查找)
- java点击车次显示详情_Web项目专项训练——火车车次信息管理系统代码分享
- 使用自定义RRT*全局规划器建图导航
- python 存储bmp格式图片
- canvas坐标转换屏幕坐标_Canvas坐标系转换