1. 程式人生 > >java-web中生成文檔(一)

java-web中生成文檔(一)

all 檢查 download com ftl 緩沖 getc cor tps

基於Java的解決方案也是很多的,包括使用Jacob、Apache POI、Java2Word、iText等各種方式,其實在從Office 2003開始,就可以將Office文檔轉換成XML文件,這樣只要將需要填入的內容放上${}占位符,就可以使用像Freemarker這樣的模板引擎將出現占位符的地方替換成真實數據,這種方式較之其他的方案要更為簡單。

舉個項目中實際的例子,先編輯一個word文擋

技術分享

1:將文檔另存為成xml格式:

技術分享

2:另存之後建議用 Editplus、Notepad++、Sublime等工具打開查看一下,因為有的時候你寫的占位符可能會被拆開,這樣Freemarker就無法處理 了。處理成如下圖所示:

技術分享

3:然後另存為.ftl格式(選擇支持所有的格式),好了非代碼的部分完成,開始搭建自己的項目,我使用的服務器是Tomcat 7.0.52,myelcipse2014;如果是eclipse需要配置web.xml支持servlet3的註解,在搭建項目之前需要向項目中加入freemarker的JAR文件,可以通過下面的鏈接獲得Freemarker的最新版本:http://freemarker.org/freemarkerdownload.html

我搭建的是一個maven 的項目,進入當中找到pom文件所需有的配置文件http://mvnrepository.com/artifact/org.freemarker/freemarker

技術分享

4.完成jsp的網頁代碼,當中要明白name的命名一定是與ftl文件中的值是對應的,這樣才能取到值。上傳jsp代碼

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<[email protected]
/* */ prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <base href="<%=basePath%>"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <style type="text/css"> * { font-family: "微軟雅黑"; } .textField { border:none; border-bottom: 1px solid gray; text-align: center; } #file { border:1px solid black; width: 80%; margin:0 auto; } h1 input{ font-size:72px; } td textarea { font-size: 14px; } .key { width:125px; font-size:20px; } </style> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>繳 費 通 知 單</title> </head> <body> <form action="saveDocServlet.s" method="post"> <div id="file" align="center"> <h1>繳 費 通 知 單</h1> <hr/> <table width="750" border="1"> <tr><td width="120" class="key">費項到期時間</td> <td height="39" colspan="3"><input type="text" name="ecEndtimeCost" class="textField" value="${param.ecEndtimeCost }" style="border:0px"/><span style="text-align:right">日</span></td> </tr> <tr> <td class="key">姓名</td> <td width="212"><input type="text" name="uname" class="textField" value="${param.uname}" style="border:0px"/></td> <td width="80" class="key">房號:</td> <td width="355"> <input type="text" name="room" value="${param.room}" style="border:0px"/> </td> </tr> <tr> <td class="key">電費:</td> <td><input type="text" name="ecElectricityFee" class="textField" style="border:0px" value="${param.ecElectricityFee }"/>元</td> <td class="key">水費:</td> <td><input type="text" name="ecWaterFee" class="textField" style="border:0px" value="${param.ecWaterFee }"/>元</td> </tr> <tr> <td class="key">物業管理費:</td> <td><input type="text" name="ecPropertyFee" class="textField" style="border:0px" value="${param.ecPropertyFee }"/>元</td> <td class="key">停車費:</td> <td><input type="text" name="ecParkingFee" class="textField" style="border:0px" value="${param.ecParkingFee }"/>元</td> </tr> <tr> <td height="39" colspan="4" class="key"> 合計金額: <input name="text" style="border: 0px; width:5px " /> 萬 <input name="text" style="border: 0px; width:5px " /> 仟<input name="text" style="border: 0px; width:5px " /> 佰 <input name="text" style="border: 0px; width:5px " /> 拾 <input name="text" style="border: 0px; width:5px " /> 元 <input style="border: 0px; width:5px " /> 角 <input name="text" style="border: 0px; width:5px " /> 分 &nbsp;&nbsp;小寫:<input name="ecAssessment" style="border: 0px; " value="${param.ecAssessment }" /></td> </tr> </table> <p >友情提醒:1、請業主在<input name="ecFeesDeadline" style="border: 0px; " value="${param.ecFeesDeadline }" /> 日前來小區物業服務處繳費,如有不便可通知物業上門收費,</p> <p >物業服務熱線:027-86889888 ,超過規定月份未交的將按有關規定加收滯納金。</p> <p>2、如認為通知單上有錯誤,可到物業服務處查對,以電腦收費臺帳上的金額為準。</p> </br> <p style=" position:relative left:600px"> <input name="text" style="border: 0px; width:25px " /> 年<input name="text" style="border: 0px; width:25px " /> 月 <input name="text" style="border: 0px; width:25px " /> 日</p> </div> <div align="center" style="margin-top:15px;"> <input type="submit" value="保存Word文檔" /> </div> </form> </body> </html>

(註意param這個el表達式對象不能用到word文檔取值,保證name的值一致就行)

我在把spring-mvc中的控制器代碼,給一份;如果你用servlet去寫也可以,但是要支持webservice註解的需要用到servlet3.0,這是就需要去web.xml容器中寫配置文件

技術分享

如果不支持就麻煩了,所以我使用springmvc的核心控制器寫的,不多說了給代碼

package com.controller.zy;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.lovo.util.WordGenerator;
@Controller
public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L; 
    @RequestMapping("/saveDocServlet.s")
    protected void service(HttpServletRequest req, HttpServletResponse resp)  
            throws ServletException, IOException {  
        req.setCharacterEncoding("utf-8");  
        Map<String, Object> map = new HashMap<String, Object>();  
        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, "zhy");  
            fin = new FileInputStream(file);  
              
            resp.setCharacterEncoding("utf-8");  
            resp.setContentType("application/msword");  
            // 設置瀏覽器以下載的方式處理該文件默認名為zhy.doc  
            resp.addHeader("Content-Disposition", "attachment;filename=zhy.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(); // 刪除臨時文件  
        }  
    }  
}

5,還要有個工具類作為中間調用的方法使用,不用多想,代碼是固定的,拿著改文件名就可以

package com.lovo.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.template.Configuration;  
import freemarker.template.Template;  
  
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/lovo/ftl");  
        allTemplates = new HashMap<>();   // Java 7 鉆石語法  
        try {  
            allTemplates.put("zhy", configuration.getTemplate("zhy.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;  
    }  
  
}  

到這裏已經完成了代碼,部署到服務器就可以使用了,希望能夠幫到你。

java-web中生成文檔(一)