1. 程式人生 > >springboot+freemarker實現生成資料庫設計Word文件

springboot+freemarker實現生成資料庫設計Word文件

      以前在專案完成後都會按照要求寫資料庫設計文件,表少的時候還無所謂,當有上百張表的時候就不好寫了。當然也有一些自動化軟體可以幫我們實現這個功能,但是自定義的程度比較低。所以今天自己來實現這個功能,可以按照自己的喜好定義樣式和模板,是不是很酷。

首先新建一個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.");
        }
    }

}


檢視控制檯資訊,檔案已經生成。

 我們去檔案目錄下檢視文件。

是不是很方便,終於可以隨心所欲的寫Word了。除了能生成資料庫設計文件,我們還可以生成其他有固定模式的Word文件,大家可以根據自己業務場景試一試。

上面只貼了一部分程式碼,詳細程式碼可以到github上下載mindoc