springboot+freemarker实现生成数据库设计Word文档

      以前在项目完成后都会按照要求写数据库设计文档,表少的时候还无所谓,当有上百张表的时候就不好写了。当然也有一些自动化软件可以帮我们实现这个功能,但是自定义的程度比较低。所以今天自己来实现这个功能,可以按照自己的喜好定义样式和模板,是不是很酷。

首先新建一个Word文档

springboot+freemarker实现生成数据库设计Word文档

 然后另存为xml格式,用NotePad打开。

在xml中使用freemarker的标签将数据填充。不会freemarker的可以先自己研究一下。

<w:body>
    <wx:sect>
        //循环遍历所有table
	<#list tables as table>
      <w:p wsp:rsidR="0017374B" wsp:rsidRPr="00481323" wsp:rsidRDefault="00AD2DC7">
        <w:pPr>
          <w:rPr>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
        </w:pPr>
        <w:r wsp:rsidRPr="00481323">
          <w:rPr>
            <wx:font wx:val="宋体"/>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
          <w:t>表名</w:t>
        </w:r>
        <w:r wsp:rsidRPr="00481323">
          <w:rPr>
            <w:rFonts w:hint="fareast"/>
            <wx:font wx:val="宋体"/>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
          <w:t>:</w:t>
        </w:r>
        <w:r wsp:rsidRPr="00481323">
          <w:rPr>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
          <w:t>${table.tableName}    </w:t>
        </w:r>
        <w:r wsp:rsidRPr="00481323">
          <w:rPr>
            <wx:font wx:val="宋体"/>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
          <w:t>注释</w:t>
        </w:r>
        <w:r wsp:rsidRPr="00481323">
          <w:rPr>
            <w:rFonts w:hint="fareast"/>
            <wx:font wx:val="宋体"/>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
          <w:t>:</w:t>
        </w:r>
        <w:r wsp:rsidR="005A39AB">
          <w:rPr>
            <w:b/>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
          <w:t>${table.tableComment} </w:t>
        </w:r>
      </w:p>
      <w:tbl>
        <w:tblPr>
          <w:tblW w:w="0" w:type="auto"/>
          <w:tblBorders>
            <w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
            <w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
            <w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
            <w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
            <w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
            <w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
          </w:tblBorders>
          <w:tblLook w:val="04A0"/>
        </w:tblPr>
        <w:tblGrid>
          <w:gridCol w:w="1659"/>
          <w:gridCol w:w="1659"/>
          <w:gridCol w:w="1659"/>
          <w:gridCol w:w="1659"/>
          <w:gridCol w:w="1660"/>
        </w:tblGrid>
        <w:tr wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidTr="00FA35C4">
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="AEAAAA"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00DE1640">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r wsp:rsidRPr="00FA35C4">
                <w:rPr>
                  <w:rFonts w:hint="fareast"/>
                  <wx:font wx:val="宋体"/>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>列名</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="AEAAAA"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00DE1640">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r wsp:rsidRPr="00FA35C4">
                <w:rPr>
                  <w:rFonts w:hint="fareast"/>
                  <wx:font wx:val="宋体"/>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>数据类型</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="AEAAAA"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00DE1640">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r wsp:rsidRPr="00FA35C4">
                <w:rPr>
                  <w:rFonts w:hint="fareast"/>
                  <wx:font wx:val="宋体"/>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>约束</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="AEAAAA"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00DE1640">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r wsp:rsidRPr="00FA35C4">
                <w:rPr>
                  <w:rFonts w:hint="fareast"/>
                  <wx:font wx:val="宋体"/>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>允许空</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1660" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="AEAAAA"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00DE1640">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r wsp:rsidRPr="00FA35C4">
                <w:rPr>
                  <w:rFonts w:hint="fareast"/>
                  <wx:font wx:val="宋体"/>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>备注</w:t>
              </w:r>
            </w:p>
          </w:tc>
        </w:tr>
		<#list table.columns as column>
        <w:tr wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidTr="00FA35C4">
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00D01744">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r>
                <w:rPr>
                  <w:rFonts w:hint="fareast"/>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>${column.columnName}</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00D01744">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>${column.columnType}</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="00D01744">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>${column.columnKey}</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1659" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="001C4911">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>${column.isNullable}</w:t>
              </w:r>
            </w:p>
          </w:tc>
          <w:tc>
            <w:tcPr>
              <w:tcW w:w="1660" w:type="dxa"/>
              <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
            </w:tcPr>
            <w:p wsp:rsidR="00DE1640" wsp:rsidRPr="00FA35C4" wsp:rsidRDefault="003F3E19">
              <w:pPr>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
              </w:pPr>
              <w:r>
                <w:rPr>
                  <w:sz w:val="18"/>
                  <w:sz-cs w:val="18"/>
                </w:rPr>
                <w:t>${column.columnComment}</w:t>
              </w:r>
            </w:p>
          </w:tc>
        </w:tr>
	  </#list>
      </w:tbl>
      <w:p wsp:rsidR="00DE1640" wsp:rsidRDefault="00DE1640">
        <w:pPr>
          <w:rPr>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
        </w:pPr>
      </w:p>
      <w:p wsp:rsidR="00913083" wsp:rsidRPr="00481323" wsp:rsidRDefault="00913083">
        <w:pPr>
          <w:rPr>
            <w:sz w:val="18"/>
            <w:sz-cs w:val="18"/>
          </w:rPr>
        </w:pPr>
      </w:p>
      <w:sectPr wsp:rsidR="00913083" wsp:rsidRPr="00481323" wsp:rsidSect="00BB620F">
        <w:pgSz w:w="11906" w:h="16838"/>
        <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992" w:gutter="0"/>
        <w:cols w:space="425"/>
        <w:docGrid w:type="lines" w:line-pitch="312"/>
      </w:sectPr>
	 </#list>
    </wx:sect>
  </w:body>

 

关键部分到了,从数据库中获取所有的表信息并将数据填充到模板中生成doc文件。

package com.dwl.mindoc.service;

import com.dwl.mindoc.dao.BaseDao;
import com.dwl.mindoc.database.BaseFactory;
import com.dwl.mindoc.database.Database;
import com.dwl.mindoc.domain.TableVo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: mindoc
 * @description: generator
 * @author: daiwenlong
 * @create: 2018-10-13 13:00
 **/
@Service
public class GenerateService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private BaseFactory factory;

    @Autowired
    private BaseDao dao;

    @PostConstruct
    public void genertator(){
        try {
            Database base = factory.getDataBase();
            List<TableVo> tables = dao.getTables(base);
            tables.forEach(table->{
                table.setColumns(dao.getColumns(base,table.getTableName()));
                logger.info("mindoc - TableName:{} TableComment:{} loading...",table.getTableName(),table.getTableComment());
            });
            makeDoc(tables);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 生成doc
     * @param tables
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    public void makeDoc(List<TableVo> tables){
        logger.info("mindoc - makeDoc Satrting...");
        // 第一步:创建一个Configuration对象。
        Configuration configuration = new Configuration(Configuration.getVersion());
        // 第二步:设置模板文件所在的路径。
        try {
            configuration.setDirectoryForTemplateLoading(ResourceUtils.getFile("classpath:"));
            // 第三步:设置模板文件使用的字符集。
            configuration.setDefaultEncoding("utf-8");
            // 第四步:加载一个模板,创建一个模板对象。
            Template template = configuration.getTemplate("doc.xml");
            // 第五步:创建一个模板使用的数据集。
            Map<String,Object> dataModel = new HashMap<>();
            dataModel.put("tables",tables);
            //生成文件放在项目根目录下
            File outFile = new File(System.getProperty("user.dir")+"\\DatabaseDesign.doc");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            // 第六步:调用模板对象的process方法输出文件。
            template.process(dataModel, out);
            logger.info("mindoc - MakeDoc succeeded.");
            logger.info("mindoc - Doc directory {}",outFile);
        } catch (IOException |TemplateException e) {
            logger.warn("mindoc - MakeDoc failed.");
        }
    }

}


查看控制台信息,文件已经生成。

springboot+freemarker实现生成数据库设计Word文档

 我们去文件目录下查看文档。

springboot+freemarker实现生成数据库设计Word文档

 

是不是很方便,终于可以随心所欲的写Word了。除了能生成数据库设计文档,我们还可以生成其他有固定模式的Word文档,大家可以根据自己业务场景试一试。

上面只贴了一部分代码,详细代码可以到github上下载mindoc