代码生成器,由表数据,表名,列名转换为类名,属性名,生成类,此生成器只提供一个思路,模板依据原理自己实现。
1,导入pom依赖
<!-- 引入SpringBoot父类依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.22.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
<mysql.version>5.1.38</mysql.version>
<druid.version>1.0.28</druid.version>
<commons.lang.version>2.6</commons.lang.version>
<commons.io.version>2.5</commons.io.version>
<commons.configuration.version>1.10</commons.configuration.version>
<fastjson.version>1.2.31</fastjson.version>
<velocity.version>1.7</velocity.version>
</properties>
<dependencies>
<!-- springboot-web组件 springmvc+spring+mybatis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>${commons.configuration.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<artifactId>velocity</artifactId>
<groupId>org.apache.velocity</groupId>
<version>${velocity.version}</version>
</dependency>
</dependencies>
二,整理配置文件
application.yml
# Tomcat
server:
tomcat:
max-threads: 10
min-spare-threads: 10
port: 8090
# mysql 用户,密码,库自己修改配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.25.130:3306/chong?useUnicode=true&characterEncoding=UTF-8
username: root
password: xxxxxx
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
resources:
static-locations: classpath:/static/,classpath:/views/
# Mybatis配置
mybatis:
mapperLocations: classpath:mapper/**/*.xml
三 ,添加生成器模板配置文件
generator.properties
#\u8DEF\u5F84
mainPath=com.liu
#\u6A21\u5757
package=com.liu.modules
moduleName=log
#\u6CE8\u91CA
author=liuerchong
#Email
email=xxxxxx@xxx.com
#\u7C7B\u578B\u8F6C\u6362\uFF0C\u914D\u7F6E\u4FE1\u606F
tinyint=Integer
smallint=Integer
mediumint=Integer
int=Integer
integer=Integer
bigint=Long
float=Float
double=Double
decimal=BigDecimal
bit=Boolean
char=String
varchar=String
tinytext=String
text=String
mediumtext=String
longtext=String
date=Date
datetime=Date
timestamp=Date
四,添加模板文件 ,此处类具体实现可根据实际自行处理,比如返回值类型ResultInfo
Controller.java.vm
package ${package}.controller;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestBody;
import ${package}.entity.${className}Entity;
import ${package}.service.${className}Service;
/**
* ${comments}
*
* @author ${author}
*
* @date ${datetime}
*/
@RestController
@RequestMapping("/${moduleName}/${pathName}")
public class ${className}Controller {
@Autowired
private ${className}Service ${classname}Service;
/**
* 列表
*/
@RequestMapping("/list")
@RequiresPermissions("${moduleName}:${pathName}:list")
public ResultInfo list(@RequestParam Map<String, Object> params){
//查询列表数据
Query query = new Query(params);
List<${className}Entity> ${classname}List = ${classname}Service.queryList(query);
int total = ${classname}Service.queryTotal(query);
PageUtils pageUtil = new PageUtils(${classname}List, total, query.getLimit(), query.getPage());
return ResultInfo.ok().put("page", pageUtil);
}
/**
* 信息
*/
@RequestMapping("/info/{${pk.attrname}}")
@RequiresPermissions("${moduleName}:${pathName}:info")
public ResultInfo info(@PathVariable("${pk.attrname}") ${pk.attrType} ${pk.attrname}){
${className}Entity ${classname} = ${classname}Service.queryObject(${pk.attrname});
return ResultInfo.ok().put("${classname}", ${classname});
}
/**
* 保存
*/
@RequestMapping("/save")
@RequiresPermissions("${moduleName}:${pathName}:save")
public ResultInfo save(@RequestBody ${className}Entity ${classname}){
${classname}Service.save(${classname});
return ResultInfo.ok();
}
/**
* 修改
*/
@RequestMapping("/update")
@RequiresPermissions("${moduleName}:${pathName}:update")
public ResultInfo update(@RequestBody ${className}Entity ${classname}){
${classname}Service.update(${classname});
return ResultInfo.ok();
}
/**
* 删除
*/
@RequestMapping("/delete")
@RequiresPermissions("${moduleName}:${pathName}:delete")
public ResultInfo delete(@RequestBody ${pk.attrType}[] ${pk.attrname}s){
${classname}Service.deleteBatch(${pk.attrname}s);
return ResultInfo.ok();
}
}
五,实现模板工具方法
package com.liu.utils;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import com.liu.entity.ColumnEntity;
import com.liu.entity.TableEntity;
/**
* 代码生成器 工具类
*
*/
public class GenUtils {
public static List<String> getTemplates(){
List<String> templates = new ArrayList<String>();
// templates.add("template/Entity.java.vm");
// templates.add("template/Dao.java.vm");
// templates.add("template/Dao.xml.vm");
// templates.add("template/Service.java.vm");
// templates.add("template/ServiceImpl.java.vm");
templates.add("template/Controller.java.vm");
return templates;
}
/**
* 生成代码
*/
public static void generatorCode(Map<String, String> table,List<Map<String, String>> columns, ZipOutputStream zip) {
//配置信息
Configuration config = getConfig();
boolean hasBigDecimal = false;
//表信息
TableEntity tableEntity = new TableEntity();
tableEntity.setTableName(table.get("tableName" ));
tableEntity.setComments(table.get("tableComment" ));
//表名转换成Java类名
String className = tableToJava(tableEntity.getTableName(), config.getString("tablePrefix" ));
tableEntity.setClassName(className);
tableEntity.setClassname(StringUtils.uncapitalize(className));
//列信息
List<ColumnEntity> columsList = new ArrayList<ColumnEntity>();
for(Map<String, String> column : columns){
ColumnEntity columnEntity = new ColumnEntity();
columnEntity.setColumnName(column.get("columnName" ));
columnEntity.setDataType(column.get("dataType" ));
columnEntity.setComments(column.get("columnComment" ));
columnEntity.setExtra(column.get("extra" ));
//列名转换成Java属性名
String attrName = columnToJava(columnEntity.getColumnName());
columnEntity.setAttrName(attrName);
columnEntity.setAttrname(StringUtils.uncapitalize(attrName));
//列的数据类型,转换成Java类型
String attrType = config.getString(columnEntity.getDataType(), "unknowType" );
columnEntity.setAttrType(attrType);
if (!hasBigDecimal && attrType.equals("BigDecimal" )) {
hasBigDecimal = true;
}
//是否主键
if ("PRI".equalsIgnoreCase(column.get("columnKey" )) && tableEntity.getPk() == null) {
tableEntity.setPk(columnEntity);
}
columsList.add(columnEntity);
}
tableEntity.setColumns(columsList);
//没主键,则第一个字段为主键
if (tableEntity.getPk() == null) {
tableEntity.setPk(tableEntity.getColumns().get(0));
}
//设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
Velocity.init(prop);
String mainPath = config.getString("mainPath" );
mainPath = StringUtils.isBlank(mainPath) ? "com.suke.czx" : mainPath;
//封装模板数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("tableName", tableEntity.getTableName());
map.put("comments", tableEntity.getComments());
map.put("pk", tableEntity.getPk());
map.put("className", tableEntity.getClassName());
map.put("classname", tableEntity.getClassname());
map.put("pathName", tableEntity.getClassname().toLowerCase());
map.put("columns", tableEntity.getColumns());
map.put("hasBigDecimal", hasBigDecimal);
map.put("mainPath", mainPath);
map.put("package", config.getString("package" ));
map.put("moduleName", config.getString("moduleName" ));
map.put("author", config.getString("author" ));
map.put("email", config.getString("email" ));
map.put("datetime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
VelocityContext context = new VelocityContext(map);
//获取模板列表
List<String> templates = getTemplates();
for (String template : templates) {
//渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8" );
tpl.merge(context, sw);
try {
//添加到zip
zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), config.getString("package" ), config.getString("moduleName" ))));
IOUtils.write(sw.toString(), zip, "UTF-8" );
IOUtils.closeQuietly(sw);
zip.closeEntry();
} catch (IOException e) {
throw new RuntimeException("渲染模板失败,表名:" + tableEntity.getTableName(), e);
}
}
}
/**
* 列名转换成Java属性名
*/
public static String columnToJava(String columnName) {
return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "" );
}
/**
* 表名转换成Java类名
*/
public static String tableToJava(String tableName, String tablePrefix) {
if (StringUtils.isNotBlank(tablePrefix)) {
tableName = tableName.replace(tablePrefix, "" );
}
return columnToJava(tableName);
}
/**
* 获取配置信息
*/
public static Configuration getConfig() {
try {
return new PropertiesConfiguration("generator.properties" );
} catch (ConfigurationException e) {
throw new RuntimeException("获取配置文件失败,", e);
}
}
/**
* 获取文件名
*/
public static String getFileName(String template, String className, String packageName, String moduleName) {
String packagePath = "main" + File.separator + "java" + File.separator;
if (StringUtils.isNotBlank(packageName)) {
packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
}
if (template.contains("Entity.java.vm" )) {
return packagePath + "entity" + File.separator + className + "Entity.java";
}
if (template.contains("Dao.java.vm" )) {
return packagePath + "dao" + File.separator + className + "Dao.java";
}
if (template.contains("Service.java.vm" )) {
return packagePath + "service" + File.separator + className + "Service.java";
}
if (template.contains("ServiceImpl.java.vm" )) {
return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
}
if (template.contains("Controller.java.vm" )) {
return packagePath + "controller" + File.separator + className + "Controller.java";
}
if (template.contains("Dao.xml.vm" )) {
return "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + moduleName + File.separator + className + "Dao.xml";
}
if (template.contains("list.html.vm" )) {
return "main" + File.separator + "resources" + File.separator + "views" + File.separator
+ "modules" + File.separator + moduleName + File.separator + className.toLowerCase() + ".html";
}
if (template.contains("list.js.vm" )) {
return "main" + File.separator + "resources" + File.separator + "static" + File.separator + "js" + File.separator
+ "modules" + File.separator + moduleName + File.separator + className.toLowerCase() + ".js";
}
if (template.contains("menu.sql.vm" )) {
return className.toLowerCase() + "_menu.sql";
}
return null;
}
}
六,数据库表数据,列数据mapper,实体类
package com.liu.dao;
import java.util.List;
import java.util.Map;
/**
*
* @author liuerchong
*
*/
public interface SysGeneraterMapper {
List<Map<String, Object>> queryList(Map<String, Object> map);
int queryTotal(Map<String, Object> map);
Map<String, String> queryTable(String tableName);
List<Map<String, String>> queryColumns(String tableName);
}
<?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">
<mapper namespace="com.liu.dao.SysGeneraterMapper">
<select id="queryList" resultType="map">
select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables
where table_schema = (select database())
<if test="tableName != null and tableName.trim() != ''">
and table_name like concat('%', #{tableName}, '%')
</if>
order by create_time desc
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="queryTotal" resultType="int">
select count(*) from information_schema.tables where table_schema = (select database())
<if test="tableName != null and tableName.trim() != ''">
and table_name like concat('%', #{tableName}, '%')
</if>
</select>
<select id="queryTable" resultType="map">
select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables
where table_schema = (select database()) and table_name = #{tableName}
</select>
<select id="queryColumns" resultType="map">
select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns
where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position
</select>
</mapper>
package com.liu.entity;
/**
*
* @author liuerchong
*
*/
public class ColumnEntity {
//列名
private String columnName;
//列名类型
private String dataType;
//列名备注
private String comments;
//属性名称(第一个字母大写),如:user_name => UserName
private String attrName;
//属性名称(第一个字母小写),如:user_name => userName
private String attrname;
//属性类型
private String attrType;
//auto_increment
private String extra;
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getAttrname() {
return attrname;
}
public void setAttrname(String attrname) {
this.attrname = attrname;
}
public String getAttrName() {
return attrName;
}
public void setAttrName(String attrName) {
this.attrName = attrName;
}
public String getAttrType() {
return attrType;
}
public void setAttrType(String attrType) {
this.attrType = attrType;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}
package com.liu.entity;
import java.util.List;
/**
* 表数据
*
* @author czx
* @email object_czx@163.com
* @date 2016年12月20日 上午12:02:55
*/
public class TableEntity {
//表的名称
private String tableName;
//表的备注
private String comments;
//表的主键
private ColumnEntity pk;
//表的列名(不包含主键)
private List<ColumnEntity> columns;
//类名(第一个字母大写),如:sys_user => SysUser
private String className;
//类名(第一个字母小写),如:sys_user => sysUser
private String classname;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public ColumnEntity getPk() {
return pk;
}
public void setPk(ColumnEntity pk) {
this.pk = pk;
}
public List<ColumnEntity> getColumns() {
return columns;
}
public void setColumns(List<ColumnEntity> columns) {
this.columns = columns;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
}
七,service 类,实现代码生成
package com.liu.service;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.liu.dao.SysGeneraterMapper;
import com.liu.utils.GenUtils;
/**
* 代码生成器
*
*/
@Service
public class SysGeneratorService {
@Autowired
private SysGeneraterMapper sysGeneraterMapper ;
public List<Map<String, Object>> queryList(Map<String, Object> map) {
return sysGeneraterMapper.queryList(map);
}
public int queryTotal(Map<String, Object> map) {
return sysGeneraterMapper.queryTotal(map);
}
public Map<String, String> queryTable(String tableName) {
return sysGeneraterMapper.queryTable(tableName);
}
public List<Map<String, String>> queryColumns(String tableName) {
return sysGeneraterMapper.queryColumns(tableName);
}
public byte[] generatorCode(String[] tableNames) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
for(String tableName : tableNames){
//查询表信息
Map<String, String> table = queryTable(tableName);
//查询列信息
List<Map<String, String>> columns = queryColumns(tableName);
//生成代码
GenUtils.generatorCode(table, columns, zip);
}
IOUtils.closeQuietly(zip);
return outputStream.toByteArray();
}
}
八,测试controller
package com.liu.controller;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.management.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON;
import com.liu.service.SysGeneratorService;
/**
* 代码生成器
*
*/
@Controller
@RequestMapping("/generator")
public class SysGeneratorController {
@Autowired
private SysGeneratorService sysGeneratorService;
/**
* 生成代码
*/
@RequestMapping("/code")
public void code(HttpServletRequest request, HttpServletResponse response) throws IOException{
String[] tableNames = new String[]{};
//String tables = request.getParameter("tables");
//此处数据应为前台,传递过来,为测试方便,测试数据写于此处,此处表名应选择数据库存在的表
String tables = "[\"sys_log_OperateDetail\"]";
tableNames = JSON.parseArray(tables).toArray(tableNames);
byte[] data = sysGeneratorService.generatorCode(tableNames);
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"x-springboot.zip\"");
response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8");
IOUtils.write(data, response.getOutputStream());
}
}
九,入口类
package com.liu;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = { "com.liu" })
@MapperScan("com.liu.dao")
@SpringBootApplication
public class App {
public static void main(String[] args) {
// 主函数运行springboot项目
SpringApplication.run(App.class, args);
}
}
十,输入连接测试,文件以zip下载下来