java Web项目中通过FreeMarker生成指定格式的Word文档

1.首先需要借助office将需要的word模板转成xml文件

在此操作之前需要将需要填入内容的地方用${name}进行占位,其中name为属性值,可以为map的key。
如下图:

Paste_Image.png

其中keycodeunitname为我接下来需要填入的相应框中的一个查询结果的类中的两个属性,当然为了处理的方便我也将它们存入了一个map

设计好模板后然后用word(ps:WPS不行)的另存为功能,存为xml文件。

2.将xml文件转为ftl文件

接下来我们需要处理一下转成的xml文件,因为有时这些占位符的内容会被一对格式分开,这样的话freemarker引擎就无法正常解析了
需要成为如下的样子,也就是保持占位符还是书写时的样子

Paste_Image.png

修改完毕后保存,然后将其另存为ftl格式的文件

3.引入freemarkerjar包

可去如下地址下载:
http://freemarker.org/freemarkerdownload.html

4.主要代码

Paste_Image.png

上图是我的web程序有关导出word的主要部分,jar放在lib下
这里我用的struts2当然servlet springmvc也是可以的

/**
     * 将新增的查封出一个审批表
     * @throws IOException 
     */
    public void exportCFw() throws IOException {
        Session session = SessionHelper.currentSession();
        HttpServletRequest req = ServletActionContext.getRequest();
        HttpServletResponse response=ServletActionContext.getResponse();
        Map<String, Object> map = new HashMap<String, Object>();
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            cfkId="0000C3C1-DC90-4A3A-A5B3-3104623C64C5";
            req.setCharacterEncoding("utf-8");
            Query query = session.createQuery("from Cfk c where c.proid='" + cfkId + "'");
            Cfk cfk = (Cfk) query.list().get(0);
            // 为了通用性将model类存储为map
            map = ConvertModel2Map(map, cfk);
            // 调用工具类WordGenerator的createDoc方法生成Word文档  
            file=WordGenerator.createDoc(map, "cfk");
            fin=new FileInputStream(file);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            response.setHeader("Content-Disposition", "attachment;filename=cfk.doc");
            out=response.getOutputStream();
            byte[] buffer=new byte[512];
            int byteToRead=-1;
            while((byteToRead=fin.read(buffer))!=-1){
                out.write(buffer, 0, byteToRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(fin != null) fin.close();  
            if(out != null) out.close();  
            if(file != null) file.delete(); // 删除临时文件  
            
        }

    }

    private Map<String, Object> ConvertModel2Map(Map<String, Object> map, Object model) {
        Field[] fields = model.getClass().getDeclaredFields();// 获取实体类的所有属性,返回Field数组
        try {
            for (Field field : fields) { // 遍历所有属性
                String name = field.getName(); // 获取属性的名字
                field.setAccessible(true);// 设置当前对象对model私有属性的访问权限
                Object value = field.get(model);// 获取属性值
                if(value==null){
                    value="";
                }
                map.put(name, value);
            }
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return map;
    }
package com.fquery.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateNotFoundException;

public class WordGenerator {
    private static Configuration configuration=null;
    private static Map<String, Template> allTemplates = null;  
    static{
        configuration=new Configuration();
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(WordGenerator.class, "/com/fquery/ftl");
        allTemplates=new HashMap<String, Template>();
        try {
            allTemplates.put("cfk", configuration.getTemplate("cfk.ftl"));
        
        } catch (IOException e) {
            e.printStackTrace();
             throw new RuntimeException(e);
        }
    }
    
    private WordGenerator() {  
        throw new AssertionError();  
    }
     public static File createDoc(Map<?, ?> dataMap, String type) {  
            String name = "temp" + (int) (Math.random() * 100000) + ".doc";  
            File f = new File(name);  
            Template t = allTemplates.get(type);  
            try {  
                // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开  
                Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");  
                t.process(dataMap, w);  
                w.close();  
            } catch (Exception ex) {  
                ex.printStackTrace();  
                throw new RuntimeException(ex);  
            }  
            return f;  
        }  

}

struts2

        <action name="exportCFw" class="com.fquery.action.Export" method="exportCFw">
        </action>

前端调用action
这里为了测试方便,直接给了查询指定的条件,实际中应该是从前台传过去

function exportCF3(){
         location.href="exportCFw.action";    
     }

本文参考如下文章,特此感谢作者:http://blog.csdn.net/jackfrued/article/details/39449021

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,561评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,218评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,162评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,470评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,550评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,806评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,951评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,712评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,166评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,510评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,643评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,306评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,930评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,745评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,983评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,351评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,509评论 2 348

推荐阅读更多精彩内容

  • spring mvc 工作机制(原理): DispatcherServlet主要用作职责调度工作,本身主要用于控制...
    java大湿兄阅读 1,891评论 5 24
  • 目录 前言 FTL指令规则 插值规则 表达式 FreeMarker的常用指令 高级方法 前言 FreeMarker...
    garyond阅读 4,693评论 0 8
  • FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1...
    年轻小伙程序员阅读 2,965评论 0 5
  • 开心一笑 感冒了很难受,她闷在被窝里给男朋友发短信"我感冒了..."并决定如果对方回答"多喝点水"就一脚踹了他。过...
    架构师启示录阅读 14,974评论 8 13
  • 好友今天又朝我哭诉吐槽自己的男友多么多么不爱惜自己,还要给喜欢过的女生天天蚂蚁森林浇水。 我一向是让她自己决定感情...
    NUMBLER阅读 177评论 0 0