1.新增一个word输入一行字
2.保存,另存为xml格式,在网上找xml格式化,格式化一下保存。(xml很乱建议格式化一下不格式化也可以)
3.把xml文件放在项目中的某个位置。我放在 root-res下(ceshi.xml)
4.服务器后端代码 确定把map输出在哪一个xml里面
5.xml中使用${}语法获取传过来的值
1-3步略过不演示了 贴一张我的word效果
4.服务端代码
String mypath = this.getServletConfig().getServletContext().getRealPath("/");
String path = mypath + "res\\ceshi.xml";//导出 excel
String fileName = "";
Date mydate = new Date();//日期
fileName = MT.f(mydate) + "我要测试一下.docx";
String userAgent = request.getHeader("User-Agent");
boolean isMSIE = ((userAgent != null && userAgent.indexOf("MSIE") != -1) || (null != userAgent && -1 != userAgent.indexOf("like Gecko")));
//传到xml的map集合
List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
for (int i = 0; i <5 ; i++) {
//单个map xml中遍历的单个
HashMap<String, Object> map = new HashMap<>();
map.put("one", i + "测试");
map.put("two","第几页?"+i+"页");
listmap.add(map);
}
if (isMSIE) {
fileName = new String(fileName.getBytes("GBK"), "ISO8859-1");
} else {
fileName = new String(fileName.getBytes("UTF8"), "ISO8859-1");
}
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
Map<String, Object> map = new HashMap<String, Object>();
map.put("listmap", listmap);
String html = FreeMarkerUtils.parseText(path, map);
html = FreeMarkerTransfer.getHtmlFromTmplString(html, map);
OutputStream os = response.getOutputStream();
byte b[] = html.getBytes("UTF-8");// 只能输出byte数组,所以将字符串变为byte数组
os.write(b);
os.flush();
os.close();
FreeMarkUtils
package 你的包路径;
import java.io.File;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class FreeMarkerUtils {
/**
* 根据模版名称和实际数据解析生成html文本
* @param filePath 模版文件完整路径
* @param data 数据
* @return html文本
*/
public static String parseText(String filePath, Map data) {
if (StringUtils.isEmpty(filePath)) {
return "<font color='#F00'>Template not found.</font>";
}
File file = new File(filePath);
FreeMarkerTransfer trans = new FreeMarkerTransfer(file.getParent());
trans.setParams(data);
return trans.write2Str(file.getName());
}
}
FreeMarkerTransfer
package 包路径;
import java.io.File;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
/**
* 执行指定的freemarker模板,并返回html结果。
*
* @author 灵活的的胖子
*/
public class FreeMarkerTransfer {
private static final Map<String, Configuration> CONFIG_MAP = new ConcurrentHashMap<String, Configuration>();
/**
* 需要传递给FreeMarker的参数
*/
private Map<Object, Object> params = new HashMap<Object, Object>();
/**
* freemarker模板所在的目录
*/
private String templateDir = "";
/**
* @param tmplDir 模板文件的路径
*/
public FreeMarkerTransfer(String tmplDir) {
templateDir = tmplDir;
}
/**
* 增加需要传递给模板的变量,这些变量可以直接在模板中调用
*
* @param name 变量的名称。
* @param var 变量对应的对象。
*/
public void addVariable(String name , Object var) {
params.put(name, var);
}
/**
* 将freemarker文件的执行结果输出到writer对象中
*
* @param writer 输出
* @param template freemarker文件
*/
public void write(Writer writer , String template) {
try {
getConfig(templateDir).getTemplate(template).process(params, writer);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 将freemarker文件的执行结果输出成
*
* @param template 模板名称
* @return freemarker文件的执行结果
*/
public String write2Str(String template) {
StringWriter writer = new StringWriter();
this.write(writer, template);
return writer.toString();
}
/**
* 设置传递给FreeMarker的参数。
*
* @param bean 传递给FreeMarker的参数
*/
public void setParams(Map<Object, Object> bean) {
this.params = bean;
}
/**
* 根据指定目录从缓存中取得Configuration对象,如果缓存中不存在,则重新创建。
*
* @param tmplDir ftl模板所在的路径(先对于操作系统的绝对路径)。
* @return 取得FreeMarker的配置文件
* @throws Exception 构造config对象时产生的错误
*/
private static Configuration getConfig(String tmplDir) throws Exception {
Configuration config = CONFIG_MAP.get(tmplDir);
if (config != null) {
return config;
}
config = new Configuration();
config.setObjectWrapper(new DefaultObjectWrapper());
config.setDirectoryForTemplateLoading(new File(tmplDir));
// config.setEncoding(Locale.CHINA, "UTF-8");
config.setDefaultEncoding("UTF-8");
CONFIG_MAP.put(tmplDir, config);
return config;
}
/**
* 根据模板内容和实际数据解析生成html文本
* @param ftlContent 模板内容
* @param data 数据
* @return html文本
*/
public static String getHtmlFromTmplString(String ftlContent, Map data) {
if(!ftlContent.contains("<html xmlns:v='urn:schemas-microsoft-com") && !ftlContent.contains("<?xml")){
StringBuffer head = new StringBuffer(
"<html xmlns:v='urn:schemas-microsoft-com:vml'xmlns:o='urn:schemas-microsoft-com:office:office'xmlns:w='urn:schemas-microsoft-com:office:word'xmlns:m='http://schemas.microsoft.com/office/2004/12/omml'xmlns='http://www.w3.org/TR/REC-html40' xmlns='http://www.w3.org/1999/xhtml' > ");
head.append("<head>");
head.append(" <!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:TrackMoves>false</w:TrackMoves><w:TrackFormatting/><w:ValidateAgainstSchemas/><w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid><w:IgnoreMixedContent>false</w:IgnoreMixedContent><w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText><w:DoNotPromoteQF/><w:LidThemeOther>EN-US</w:LidThemeOther><w:LidThemeAsian>ZH-CN</w:LidThemeAsian><w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript><w:Compatibility><w:BreakWrappedTables/><w:SnapToGridInCell/><w:WrapTextWithPunct/><w:UseAsianBreakRules/><w:DontGrowAutofit/><w:SplitPgBreakAndParaMark/><w:DontVertAlignCellWithSp/><w:DontBreakConstrainedForcedTables/><w:DontVertAlignInTxbx/><w:Word11KerningPairs/><w:CachedColBalance/><w:UseFELayout/></w:Compatibility><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><m:mathPr><m:mathFont m:val='Cambria Math'/><m:brkBin m:val='before'/><m:brkBinSub m:val='--'/><m:smallFrac m:val='off'/><m:dispDef/><m:lMargin m:val='0'/> <m:rMargin m:val='0'/><m:defJc m:val='centerGroup'/><m:wrapIndent m:val='1440'/><m:intLim m:val='subSup'/><m:naryLim m:val='undOvr'/></m:mathPr></w:WordDocument></xml><![endif]-->");
head.append("<meta charset='UTF-8'>");
head.append("<meta name=ProgId content=Word.Document>");
head.append("<meta name=Generator content='Microsoft Word 14'>");
head.append("<meta name=Originator content='Microsoft Word 14'>");
head.append("</head>");
head.append("<body style='tab-interval: 21pt; text-justify-trim: punctuation;'>");
ftlContent = head.toString() + ftlContent + "</body></html>";
}
// 设置一个字符串模板加载器
StringTemplateLoader stringLoader = new StringTemplateLoader();
Configuration STRING_CONFIG = new Configuration();
STRING_CONFIG.setDefaultEncoding("UTF-8");
STRING_CONFIG.setTemplateLoader(stringLoader);
stringLoader.putTemplate("", ftlContent);
StringWriter writer = new StringWriter();
try {
// 获取匿名模板
STRING_CONFIG.getTemplate("").process(data, writer);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return writer.toString();
}
}
5.xml中获取方式
<w:body>
<wx:sect>
<w:p/>
<!--遍历listmap 固定格式 java后端传给map的集合名称 listmap as后面自定义名称 mymap.one 与之对应-->
<#list listmap as mymap>
<w:p>
<w:pPr>
<w:rPr>
<w:rFonts w:fareast="宋体" w:hint="default"/>
<w:lang w:val="EN-US" w:fareast="ZH-CN"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
<w:lang w:val="EN-US" w:fareast="ZH-CN"/>
</w:rPr>
<w:t>这是第几页${mymap.one},${mymap.two}</w:t>
</w:r>
</w:p>
<!--map集合是否有下一个 有的话就加一个换页符-->
<#if mymap_has_next>
<w:p>
<w:pPr>
<w:autoSpaceDE w:val="0"/>
<w:autoSpaceDN w:val="0"/>
<w:adjustRightInd w:val="0"/>
<w:ind w:right="-20"/>
<w:jc w:val="left"/>
<w:rPr>
<w:sz w:val="24"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:sz w:val="24"/>
</w:rPr>
<w:br w:type="page"/>
</w:r>
</w:p>
</#if>
</#list>
<w:sectPr>
效果:
省略几页