这个星期做数据字典功能,有一项任务就是将数据库中的每个表的字段导出,生成word文档,在综合比较网上各种技术之后,参照csdn上骆豪的博客完成了任务。
骆昊的链接:http://blog.csdn.net/jackfrued/article/details/39449021
首先打开word文档,建立自己所需要的模板,然后将word保存为XML的格式,这里可能出现的一个问题就是需要填入的内容放上${}占位符的时候可能会出现字符分离的情况,所以建议先将需要用${}占位符的地方用中文写在word里然后保存为XML的格式,再打开XML对需要用${}占位符的地方进行替换,这样就避免了字符分离的情况。推荐使用一个软件,foxe,这个软件编辑XML很方便,如下图所示,按F8可以对XML进行格式化,然后再对XML进行编辑。
将需要用${}占位符输出的字段替换好之后,将文件另存为ftl格式即可。
将freemarker的jar包导入lib之后,开始编写代码。
因为项目需要,我是需要将数据库中的表的和表的字段都读取出来,所以可以使用两层list进行封装。
首先,使用一个Java bean封装,代码如图所示
import java.util.List; public class allTables { String title; String commont; int count; List<CommonDictionary> commonDictionaries; public String getCommont() { return commont; } public void setCommont(String commont) { this.commont = commont; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public List<CommonDictionary> getCommonDictionaries() { return commonDictionaries; } public void setCommonDictionaries(List<CommonDictionary> commonDictionaries) { this.commonDictionaries = commonDictionaries; } }
这个Javabean是对表进行进行封装,然后再使用一个Javabean对表的属性进行封装,如图所示:
package cn.changhong.dictionary.domain; import java.util.Date; public class CommonDictionary { String cId; String cName; String cCommont; String cDataType; String primaryKey; String createUser; Date createTime; String updateUser; Date updateTime; String cLength; int num; String isNull; public String getIsNull() { return isNull; } public void setIsNull(String isNull) { this.isNull = isNull; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public String getcId() { return cId; } public void setcId(String cId) { this.cId = cId; } public String getcName() { return cName; } public void setcName(String cName) { this.cName = cName; } public String getcCommont() { return cCommont; } public void setcCommont(String cCommont) { this.cCommont = cCommont; } public String getcDataType() { return cDataType; } public void setcDataType(String cDataType) { this.cDataType = cDataType; } public String getPrimaryKey() { return primaryKey; } public void setPrimaryKey(String primaryKey) { this.primaryKey = primaryKey; } public String getCreateUser() { return createUser; } public void setCreateUser(String createUser) { this.createUser = createUser; } public String getUpdateUser() { return updateUser; } public void setUpdateUser(String updateUser) { this.updateUser = updateUser; } public String getcLength() { return cLength; } public void setcLength(String cLength) { this.cLength = cLength; } }
项目的结构如下图:
在WordDownController层将数据封装好。
代码如下:
package cn.changhong.dictionary.controller; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import cn.changhong.dictionary.domain.CommonDictionary; import cn.changhong.dictionary.domain.DcTable; import cn.changhong.dictionary.domain.allTables; import cn.changhong.dictionary.service.CommonDictionaryService; import cn.changhong.dictionary.util.WordGenerator; import cn.changhong.system.util.BaseDaoSupport; @Controller @RequestMapping("/word") public class WordDownController extends BaseDaoSupport { @Autowired CommonDictionaryService cs; @RequestMapping("/down") public void download(HttpServletRequest req, HttpServletResponse resp) throws IOException { req.setCharacterEncoding("utf-8"); Map<String, Object> map = new HashMap<String, Object>(); /* * map.put("title","哈哈"); map.put("num", 1); map.put("cName",2); * map.put("cCommont", 3); map.put("cDataType",4); map.put("cLength", * 5); map.put("primaryKey", 6); */ try { List<allTables> aTables = new ArrayList<allTables>(); List<DcTable> tables = cs.qureyalltables();//选出所有的表名 int j=1; for (DcTable table : tables) { int i = 1; List<CommonDictionary> colums = cs.querycolumnbytable(table.gettName());//选出每个表的属性 for (CommonDictionary column : colums) {//增加序号 column.setNum(i); if(column.getPrimaryKey().equals("0")){ column.setPrimaryKey("?"); }else if(column.getPrimaryKey().equals("1")){ column.setPrimaryKey("?"); } if(column.getIsNull().equals("0")){ column.setIsNull("?"); }else if(column.getIsNull().equals("1")){ column.setIsNull("?"); } i++; } allTables allTables = new allTables(); allTables.setTitle(table.gettName()); allTables.setCount(j); allTables.setCommont(table.gettCommont()); allTables.setCommonDictionaries(colums); aTables.add(allTables);//放入list里面 j++; } map.put("listmap", aTables);//放入map里面 } catch (Exception e) { // TODO: handle exception } /* * Enumeration<String> paramNames = req.getParameterNames(); // * 通过循环将表单参数放入键值对映射中 while(paramNames.hasMoreElements()) { String key = * paramNames.nextElement(); String value = req.getParameter(key); * map.put(key, value); } */ // 提示:在调用工具类生成Word文档之前应当检查所有字段是否完整 // 否则Freemarker的模板殷勤在处理时可能会因为找不到值而报错 这里暂时忽略这个步骤了 File file = null; InputStream fin = null; ServletOutputStream out = null; try { // 调用工具类WordGenerator的createDoc方法生成Word文档 file = WordGenerator.createDoc(map, "resume"); fin = new FileInputStream(file); resp.setCharacterEncoding("utf-8"); resp.setContentType("application/msword"); // 设置浏览器以下载的方式处理该文件默认名为resume.doc resp.addHeader("Content-Disposition", "attachment;filename=resume.doc"); out = resp.getOutputStream(); byte[] buffer = new byte[512]; // 缓冲区 int bytesToRead = -1; // 通过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } } finally { if (fin != null) fin.close(); if (out != null) out.close(); if (file != null) file.delete(); // 删除临时文件 } } }
将数据封装放到list里面,然后放入map.
在ftl 利用<#list>标签进行两次循环即可取出数据。
ftl的代码片段如下:
<w:body> <#list listmap as maps> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:bookmarkStart w:id="0" w:name="_GoBack"/> <w:bookmarkEnd w:id="0"/> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>表名:${maps.title}</w:t> </w:r> </w:p> <w:tbl> <w:tblPr> <w:tblStyle w:val="4"/> <w:tblW w:w="7304" w:type="dxa"/> <w:tblInd w:w="0" w:type="dxa"/> <w:tblBorders> <w:top w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0"/> </w:tblBorders> <w:tblLayout w:type="fixed"/> <w:tblCellMar> <w:top w:w="0" w:type="dxa"/> <w:left w:w="108" w:type="dxa"/> <w:bottom w:w="0" w:type="dxa"/> <w:right w:w="108" w:type="dxa"/> </w:tblCellMar> </w:tblPr> <w:tblGrid> <w:gridCol w:w="1217"/> <w:gridCol w:w="1217"/> <w:gridCol w:w="1217"/> <w:gridCol w:w="1217"/> <w:gridCol w:w="1218"/> <w:gridCol w:w="1218"/> </w:tblGrid> <w:tr> <w:tblPrEx> <w:tblBorders> <w:top w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0"/> </w:tblBorders> <w:tblLayout w:type="fixed"/> <w:tblCellMar> <w:top w:w="0" w:type="dxa"/> <w:left w:w="108" w:type="dxa"/> <w:bottom w:w="0" w:type="dxa"/> <w:right w:w="108" w:type="dxa"/> </w:tblCellMar> </w:tblPrEx> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>序号</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>字段</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>备注</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>数据类型</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1218" w:type="dxa"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>长度</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1218" w:type="dxa"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>是否主键</w:t> </w:r> </w:p> </w:tc> </w:tr> <#list maps.commonDictionaries as commonDictionary> <w:tr> <w:tblPrEx> <w:tblBorders> <w:top w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0"/> <w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0"/> </w:tblBorders> <w:tblLayout w:type="fixed"/> <w:tblCellMar> <w:top w:w="0" w:type="dxa"/> <w:left w:w="108" w:type="dxa"/> <w:bottom w:w="0" w:type="dxa"/> <w:right w:w="108" w:type="dxa"/> </w:tblCellMar> </w:tblPrEx> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> <w:textDirection w:val="lrTb"/> <w:vAlign w:val="top"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${commonDictionary.num}</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> <w:textDirection w:val="lrTb"/> <w:vAlign w:val="top"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${commonDictionary.cName}</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> <w:textDirection w:val="lrTb"/> <w:vAlign w:val="top"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${commonDictionary.cCommont}</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1217" w:type="dxa"/> <w:textDirection w:val="lrTb"/> <w:vAlign w:val="top"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${commonDictionary.cDataType}</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1218" w:type="dxa"/> <w:textDirection w:val="lrTb"/> <w:vAlign w:val="top"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${commonDictionary.cLength}</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="1218" w:type="dxa"/> <w:textDirection w:val="lrTb"/> <w:vAlign w:val="top"/> </w:tcPr> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${commonDictionary.primaryKey}</w:t> </w:r> </w:p> </w:tc> </w:tr> </#list> </w:tbl> <w:p> <w:pPr> <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> </w:p> <w:sectPr> <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:num="1"/> <w:docGrid w:type="lines" w:linePitch="312" w:charSpace="0"/> </w:sectPr> </#list> </w:body>
推荐使用foxe进行编辑,第一层list标签放入 <w:body>下
<w:body> <#list listmap as maps>
第二层list标签根据需要放到<w:tr>上这样就可以循环输出各个表的结构了,最后找到闭合标签放入</#list>,这样就可以实现循环了,注意:<w:tr>的闭合标签。
<#list maps.commonDictionaries as commonDictionary> <w:tr>
文档输出入下图所示: