基于springboot的freemarker创建指定格式的word文档

标签: springboot freemarker 格式 | 发表时间:2016-01-17 08:56 | 作者:爱宝贝丶
分享到:
出处:http://www.iteye.com

       在web或其他应用中,经常我们需要导出或者预览word文档,比较实际的例子有招聘网站上预览或者导出个人简历,使用POI导出excel会非常的方便,但是如果想导出word,由于其格式控制非常复杂,故而使用POI将会非常麻烦,而FreeMarker则可以较好的解决这个问题;并且,根据FreeMarker的实现原理,预览word也会变得非常简单。

       FreeMarker主要有三个部分:模板,数据源以及数据的存储。可想而知,在导出word的时候,我们必须得告诉FreeMarker我们需要导出的word的格式以及将要填充到这个word中的数据,因而模板和数据源是我们需要准备的部分。这里需要另外说明的是,FreeMarker关心的不是模板文件的类型或具体内容,其关心的是模板文件中的ftl标签和其中获取数据的表达式(这部分将在后续进行讲解)。FreeMarker的强大之处也就在这个位置,这里的模板可以是任意类型的模板,而数据源由我们按照指定的格式封装即可。那么也就是说,对于预览操作,我们如果事先制作一个html模板,点击预览后由FreeMarker向按照该模板向新建的html文件中填充数据,接着在前台js中新开窗口将该html文件(填充数据后即为一个静态页面)显示出来即可达到预览的效果。

       这里我们以word文件的导出为例来讲解FreeMarker的使用,我们使用的IDE为Intellij IDEA,框架为springboot,项目是使用Maven构建的。

       模板文件的创建可以使用word2007及以上版本完成,首先我们创建一个如下格式的word文档:

       创建后将该文件以xml格式存储


       使用xml文本编辑器打开该xml文件,检查其中的取值表达式是否发生格式错误,如果发生格式错误就将其中错误的部分删除,使其恢复我们填写的格式(格式错误一般会发生在取值表达式中含有特殊字符的时候)。

        如图中所示,${user.password}就发生了格式错误,我们将中间错误部分删除后如下:

        接着将该模板文件另存为UserList.ftl,文件格式为全部文件:

       将该文件复制到项目中,打开并格式化,找到其中${user.username}和${user.password},仔细分析该ftl文件可以发现,在word文档中表格的每一行在xml文件中即为一个<w:tr></w:tr>标签,而在该标签中,每一个<w:tc></w:tc>则对应一个单元格。了解这个之后,我们就要使用ftl语法对该模板文件进行改造。这里我们需要导出的是一个用户列表的文件,每个用户包含一个用户名和密码,那么这里用户所在的这一行(<w:tr></w:tr>)就需要使用ftl中的<#list></#list>标签包含起来:

<#list users as user>
<w:tr>
<w:tc>
...
用户名:
...
</w:tc>
<w:tc>
...
${user.username}
...
</w:tc>
<w:tc>
...
密码:
...
</w:tc>
<w:tc>
...
${user.password}
...
</w:tc>
</w:tr>
</#list>

        到此为止,我们的ftl模板就制作完毕了。接下来我们创建后台服务端的代码,实体类创建如下:

 

public class User {
  
  private String username;
  private String password;

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public User() {
  }

  public User(String username, String password) {
    this.username = username;
    this.password = password;
  }
}

        Controller层创建如下:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/word")
public class WordController {

  @Autowired
  private WordService wordService;

  @RequestMapping(value = "/createUserListWord", method = RequestMethod.GET)
  public ResponseEntity<Void> createUserListWord() {
    wordService.createUserListWord();
    return ResponseEntity.ok().build();
  }
}
        Service层的接口及其实现类如下:
public interface WordService {
  void createUserListWord();
}
 
import javax.transaction.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;
@Service
public class WordServiceImpl implements WordService {
  public void createUserListWord() {
    Map<?, ?> root = initData();  //数据源对象
    String template = "/template/UserList.ftl";  //模板文件的地址
    String path = "E:\\UserList.doc";  //生成的word文档的输出地址
    WordUtil.process(root, template, path);
  }

  private Map<?, ?> initData() {
    Map<String, Object> root = new HashMap<String, Object>();

    List<User> users = new ArrayList<User>();
    User zhangsan = new User("张三", "123");
    User lisi = new User("李四", "456");
    User wangwu = new User("王五", "789");
    users.add(zhangsan);
    users.add(lisi);
    users.add(wangwu);

    root.put("users", users);
    root.put("title", "用户列表");

    return root;
  }
}
        这里需要说明的一点是,在FreeMarker中,数据一般是以Map,List以及实体类对象的形式存储,这里数据的初始化函数中则将三种形式的数据存储方式都用到了。在模板中取值的时候,对于Map对象中的数据,使用${key}即可获取,这里key表示Map中的键,对于List,则可以使用下标的方式,也可以使用循环的方式,这里我们是将User对象存储于List中,在模板中则可以使用users[i]来获取List中第i个User对象,如users[i].username;也可以使用循环来对List集合进行遍历,如
<#list users as user>
  ${user.username}
</#list>
        这里users表示存储List的Map的key的值。

 

       最后则是FreeMarker中生成word文档的核心函数:

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public final class WordUtil {
  private static Configuration configuration = null;

  private WordUtil() {
    throw new AssertionError();
  }

  /**
   * 根据模板生成相应的文件
   * @param root 保存数据的map
   * @param template 模板文件的地址
   * @param path 生成的word文档输出地址
   * @return
   */
  public static synchronized File process(Map<?, ?> root, String template, String path) {

    if (null == root ) {
      throw new RuntimeException("数据不能为空");
    }

    if (null == template) {
      throw new RuntimeException("模板文件不能为空");
    }

    if (null == path) {
      throw new RuntimeException("输出路径不能为空");
    }

    File file = new File(path);
    String templatePath = template.substring(0, template.lastIndexOf("/"));
    String templateName = template.substring(template.lastIndexOf("/") + 1, template.length());

    if (null == configuration) {
      configuration = new Configuration(Configuration.VERSION_2_3_23);  // 这里Configurantion对象不能有两个,否则多线程访问会报错
      configuration.setDefaultEncoding("utf-8");
      configuration.setClassicCompatible(true);
    }
    configuration.setClassForTemplateLoading(WordUtil.class, templatePath);

    Template t = null;
    try {
      t = configuration.getTemplate(templateName);
      Writer w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));
      t.process(root, w);  // 这里w是一个输出地址,可以输出到任何位置,如控制台,网页等
      w.close();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return file;
  }

}
        至此,使用FreeMarker生成word文档的核心代码已经全部书写完毕,最后打开浏览器访问http://localhost:8081/word/createUserListWord,在E盘根目录下就会生成一个word文档,其内容如下:

        这只是FreeMarker的一个简单应用,关于FreeMarker生成html文件,这里有一点需要说明,word2007及以上版本保存文件的格式可以为xml文件,也可以为html文件,检查该html文件中取值表达式的格式无误之后按照上述步骤也可以生成我们需要的html文件,但是生成的html文件的格式不一定是我们需要的格式,并且在修改ftl模板的时候,由于模板中标签元素的样式等较多,因而修改较为复杂。若想达到预览的效果,我们可以不使用上述方法生成的html模板,而是手动书写一份格式一致的html文件,然后保存为ftl格式模板,这个过程并不复杂,并且可读性较强。
       以上就是本篇博客的全部内容,希望大家喜欢。


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [springboot freemarker 格式] 推荐:

基于springboot的freemarker创建指定格式的word文档

- - 互联网 - ITeye博客
       在web或其他应用中,经常我们需要导出或者预览word文档,比较实际的例子有招聘网站上预览或者导出个人简历,使用POI导出excel会非常的方便,但是如果想导出word,由于其格式控制非常复杂,故而使用POI将会非常麻烦,而FreeMarker则可以较好的解决这个问题;并且,根据FreeMarker的实现原理,预览word也会变得非常简单.

freemarker生成word

- - 开源软件 - ITeye博客
freemarker生成word.          利用freemarker生成word,在项目中有用到,就单独写个测试以及用法列出来,欢迎圈错,共同学习.       一、应用场景和效果图.             1.应用场景:.                    a.xx项目里面需要定期生成xx报告,记录最近xx情况.

SpringBoot的事务管理

- - ImportNew
Springboot内部提供的事务管理器是根据autoconfigure来进行决定的. 比如当使用jpa的时候,也就是pom中加入了spring-boot-starter-data-jpa这个starter之后(之前我们分析过 springboot的自动化配置原理). Springboot会构造一个JpaTransactionManager这个事务管理器.

springboot集成shiro 实现权限控制

- - CSDN博客编程语言推荐文章
apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自家的东西. springboot暂时没有集成shiro,这得自己配. 本文实现从数据库读取用户信息,获取当前用户的权限或角色,通过配置文件过滤用户的角色或权限.

maven工程下整合spring+mybatis+freemarker

- - CSDN博客架构设计推荐文章
博客地址:http://zhengyinhui.com/?p=142. 由于工作主要是前端开发,做后端的项目比较少,最近自己做个项目,发觉好多的都忘了,这里写篇博客整理下maven工程下整合spring+mybatis+freemarker相关内容. 新建个Archetype为maven-archetype-webapp的maven项目(安装maven插件:http://download.eclipse.org/technology/m2e/releases),在pom文件添加相关依赖:.

java导出word之freemarker导出

- - 企业架构 - ITeye博客
       一,简单模板导出(不含图片, 不含表格循环).          1, 新建一个word文档, 输入如下类容:.          2, 将该word文件另存为xml格式(注意是另存为,不是直接改扩展名).          3, 将xml文件的扩展名直接改为ftl.          4, 用java代码完成导出(需要导入freemarker.jar).

Spring整合freemarker发送邮件

- - CSDN博客推荐文章
在上一篇博文:  使用JavaMail发送邮件和接受邮件, 我们学习了原生的JavaApi发送邮件, 我们会发现代码比较多, 特别是当邮件内容很丰富的时候, 我们需要在Java中拼装Html, 是不是觉得非常麻烦. . 下面我们使用一种比较简单的方法: spring + javaMail + freemarker, 使用freemarker模板引擎后, 我们就不用再在Java中拼装html..

(转)正确、安全地停止SpringBoot应用

- - jackyrong
Spring Boot,作为Spring框架对“约定优先于配置(Convention Over Configuration)”理念的最佳实践的产物,它能帮助我们很快捷的创建出独立运行、产品级别的基于Spring框架的应用,大部分Spring Boot应用只需要非常少的配置就可以快速运行起来,是一个与微服务(MicroServices)相当契合的微框架.

用JWT技术为SpringBoot的API增加授权保护 – springcamp

- -
示例 https://github.com/qihaiyan/jwt-boot-auth. 用spring-boot开发RESTful API非常的方便,在生产环境中,对发布的API增加授权保护是非常必要的. 现在我们来看如何利用JWT技术为API增加授权保护,保证只有获得授权的用户才能够访问API.

struts2中使用freemarker 生成静态页面

- - CSDN博客推荐文章
2.导入struts2的相关jar文件. 3.在web.xml中配置如下:. 4.创建struts.xml文件,具体内容如下:. 在配置视图类型时,也可以直接用type="freemarker"这个访问指定的模板,在这里我用的是动态访问生成的html页面. 5,创建javaBean  User.java.