J2EE項(xiàng)目系列(四)--SSM框架構(gòu)建積分系統(tǒng)和基本商品檢索系統(tǒng)(Spring+SpringMVC+MyBatis)(3)Ajax使用詳解(級(jí)聯(lián)列表)以及企業(yè)級(jí)報(bào)表Excel導(dǎo)入導(dǎo)出實(shí)現(xiàn)

今天來講下企業(yè)的開發(fā)的一些功能應(yīng)用吧,就是Ajax使用,以及簡單的企業(yè)報(bào)表的導(dǎo)入導(dǎo)出,基于原有的項(xiàng)目進(jìn)行展示(其實(shí)是本博主想偷懶)。

本系列:

(一)項(xiàng)目框架整合構(gòu)建

(二)建立商品數(shù)據(jù)庫和Lucene的搭建

(三) Redis系列(一)--安裝、helloworld以及讀懂配置文件

(四)Redis系列(二)--緩存設(shè)計(jì)(整表緩存以及排行榜緩存方案實(shí)現(xiàn))

(五) Lucene總結(jié)系列(一)--認(rèn)識(shí)、helloworld以及基本的api操作。

(六)Lucene總結(jié)系列(二)--商品檢索系統(tǒng)的文字檢索業(yè)務(wù)(lucene項(xiàng)目使用)

(七)Lucene總結(jié)系列(三)--總述優(yōu)化方案和呈現(xiàn)實(shí)時(shí)內(nèi)存索引實(shí)現(xiàn)(結(jié)合RAMDirectory源碼解析)

(八)JavaWeb--Servlet過濾器Filter和SpringMVC的HandlerInterceptor(Session和Cookie登錄認(rèn)證)

(九)Redis系列(三)--過期策略

(十)Redis系列(四)--內(nèi)存淘汰機(jī)制(含單機(jī)版內(nèi)存優(yōu)化建議)


文章結(jié)構(gòu):(1)Ajax使用詳解(級(jí)聯(lián)列表例子);(2)企業(yè)級(jí)報(bào)表Excel導(dǎo)入導(dǎo)出;

一、Ajax使用詳解(級(jí)聯(lián)列表例子):

(1)概述:

AJAX 不是新的編程語言,而是一種使用現(xiàn)有標(biāo)準(zhǔn)的新方法。

AJAX 最大的優(yōu)點(diǎn)是在不重新加載整個(gè)頁面的情況下,可以與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁內(nèi)容。

AJAX 不需要任何瀏覽器插件,但需要用戶允許JavaScript在瀏覽器上執(zhí)行。

應(yīng)用:

運(yùn)用XHTML+CSS來表達(dá)資訊;
運(yùn)用JavaScript操作DOM(Document Object Model)來執(zhí)行動(dòng)態(tài)效果;
運(yùn)用XML和XSLT操作資料;
運(yùn)用XMLHttpRequest或新的Fetch API與網(wǎng)頁服務(wù)器進(jìn)行異步資料交換;
注意:AJAX與Flash、Silverlight和Java Applet等RIA技術(shù)是有區(qū)分的。

不適用:

部分簡單的表單
搜索
基本的導(dǎo)航
替換大量的文本
.對(duì)呈現(xiàn)的操縱

缺點(diǎn):轉(zhuǎn)載自此

1. AJAX干掉了Back和History功能,即對(duì)瀏覽器機(jī)制的破壞。在動(dòng)態(tài)更新頁面的情況下,用戶無法回到前一個(gè)頁面狀態(tài),因?yàn)闉g覽器僅能記憶歷史記錄中的靜態(tài)頁面。
2. AJAX的安全問題。
AJAX技術(shù)給用戶帶來很好的用戶體驗(yàn)的同時(shí)也對(duì)IT企業(yè)帶來了新的安全威脅,Ajax技術(shù)就如同對(duì)企業(yè)數(shù)據(jù)建立了一個(gè)直接通道。這使得開發(fā)者在不經(jīng)意間會(huì)暴露比以前更多的數(shù)據(jù)和服務(wù)器邏輯。Ajax的邏輯可以對(duì)客戶端的安全掃描技術(shù)隱藏起來,允許黑客從遠(yuǎn)端服務(wù)器上建立新的攻擊。還有Ajax也難以避免一些已知的安全弱點(diǎn),諸如跨站點(diǎn)腳步攻擊、SQL注入攻擊和基于Credentials的安全漏洞等等。
3. 對(duì)搜索引擎支持較弱:
對(duì)搜索引擎的支持比較弱。如果使用不當(dāng),AJAX會(huì)增大網(wǎng)絡(luò)數(shù)據(jù)的流量,從而降低整個(gè)系統(tǒng)的性能。
4. 違背URL和資源定位的初衷。
例如,我給你一個(gè)URL地址,如果采用了Ajax技術(shù),也許你在該URL地址下面看到的和我在這個(gè)URL地址下看到的內(nèi)容是不同的。這個(gè)和資源定位的初衷是相背離的。
5. 客戶端過肥,太多客戶端代碼造成開發(fā)上的成本。
編寫復(fù)雜、容易出錯(cuò) ;冗余代碼比較多(層層包含js文件是AJAX的通病,再加上以往的很多服務(wù)端代碼現(xiàn)在放到了客戶端);破壞了Web的原有標(biāo)準(zhǔn)。

簡單描述工作原理

Ajax的工作原理相當(dāng)于在用戶和服務(wù)器之間加了—個(gè)中間層(AJAX引擎),使用戶操作與服務(wù)器響應(yīng)異步化。并不是所有的用戶請(qǐng)求都提交給服務(wù)器,像—些數(shù)據(jù)驗(yàn)證和數(shù)據(jù)處理等都交給Ajax引擎自己來做, 只有確定需要從服務(wù)器讀取新數(shù)據(jù)時(shí)再由Ajax引擎代為向服務(wù)器提交請(qǐng)求。
Ajax其核心有JavaScript、XMLHTTPRequest、DOM對(duì)象組成,通過XmlHttpRequest對(duì)象來向服務(wù)器發(fā)異步請(qǐng)求,從服務(wù)器獲得數(shù)據(jù),然后用JavaScript來操作DOM而更新頁面。這其中最關(guān)鍵的一步就是從服務(wù)器獲得請(qǐng)求數(shù)據(jù)。讓我們來了解這幾個(gè)對(duì)象。

最基本的例子:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<div id="myDiv"><h2> AJAX  HelloWorld</h2></div>
<button type="button" onclick="loadXMLDoc()">修改內(nèi)容</button>
</script>
</head>
<body>

<script>
function loadXMLDoc(){
    //在里面去使用ajax做請(qǐng)求,以及更新前端UI
    var xmlhttp;
    if (window.XMLHttpRequest){
        //  IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執(zhí)行代碼
        xmlhttp=new XMLHttpRequest();
    }
    else{
        // IE6, IE5 瀏覽器執(zhí)行代碼
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);
    xmlhttp.send();
}
</script>

下面是我們今天要做的全部功能啦。

這里寫圖片描述

(2)級(jí)聯(lián)表實(shí)現(xiàn):

描述:
就是在不更新頁面情況下:商品地址,會(huì)更新下面所說的對(duì)應(yīng)賬號(hào)(博主為了偷懶,簡單寫的邏輯)。
圖片展示:
這里寫圖片描述
這里寫圖片描述
功能展示:選擇廣東省或北京市后:賬號(hào)自動(dòng)更新
這里寫圖片描述

實(shí)現(xiàn):demo代碼

(一)前端代碼:

//注意我給select添加了一個(gè)監(jiān)聽喔。
<div class="modal">
        <p>
            <label>商品地址:</label>
            <select name="location" id="location" onchange="locationChange()">
                <option value="">請(qǐng)選擇</option>
                <option value="廣東省">廣東省</option>
                <option value="北京市">北京市</option>
            </select>
        </p>
        <p>
            <label>列出對(duì)應(yīng)的賬號(hào):</label>
            <select name="accounts" id="accounts">
                <option value="">請(qǐng)選擇</option>
            </select>
        </p>
  </div>

(2)方法監(jiān)聽就看方法嘛:方法體詳解在后面(下面的例子注釋使用時(shí)請(qǐng)刪去)

//$.ajax里面就是ajax的方法啦,動(dòng)態(tài)加載:
<script>
    function locationChange() {

        var location = $("#location").find("option:selected").text();
        alert(location)
        var obj = document.getElementById('accounts');//綁定select
        obj.options.length = 0;
        obj.add(new Option("請(qǐng)選擇", ""));
        $.ajax({
            type: "post",     //請(qǐng)求類型
            url: "/ajax/findUserByProvince",   //請(qǐng)求路徑
            cache: false,                   //緩存是否啟用
            data: {location: location},     //傳參
            dataType: "json",                //期望返回的數(shù)據(jù)體
            success: function (result) {
            //result是后臺(tái)返回給前端的結(jié)果集,而我們上面期望他是一個(gè)json,所以就是個(gè)json數(shù)組咯
                if (result.length > 0) {
                    obj.add(new Option("請(qǐng)選擇", ""));
                    for (var i in result) {//遍歷取值更新select
                        var selectOption = new Option(result[i].account, result[i].account);
                        obj.add(selectOption);
                    }
                }
            }
        });
    }
</script>

(3)接下來看后端的處理:

    @ResponseBody
    @RequestMapping(value = "/findUserByProvince",produces="text/html;charset=UTF-8", method = {RequestMethod.GET,RequestMethod.POST})
    public String findUserByProvince(String location){
        List<User> userList = userService.findUserByProvince(location);//這個(gè)只是一個(gè)簡單的根據(jù)省份去查詢用戶賬號(hào)的邏輯,想了解細(xì)節(jié)下方有源碼下載
        System.out.println(JSON.toJSONString(userList));
        //返回一個(gè)json數(shù)組給前端
        return JSON.toJSONString(userList);
    }

補(bǔ)充:有朋友反應(yīng)下面這個(gè)jQuery使用看不太懂

//$("#location")是綁定了id是location的標(biāo)簽組件
//find("option:selected")是拿到上面的標(biāo)簽組件下面的option
//使用text()就是可以拿到內(nèi)容啦。
var location = $("#location").find("option:selected").text();

這就是一個(gè)簡單的級(jí)聯(lián)列表實(shí)現(xiàn),結(jié)合ajax。


(3)下面就詳細(xì)講解ajax方法體的各大參數(shù)吧:以下部分轉(zhuǎn)載此博主此博客

(一)url:

要求為String類型的參數(shù),(默認(rèn)為當(dāng)前頁地址)發(fā)送請(qǐng)求的地址。

(二)type:

要求為String類型的參數(shù),請(qǐng)求方式(post或get)默認(rèn)為get。注意其他http請(qǐng)求方法,例如put和delete也可以使用,但僅部分瀏覽器支持。

(三)timeout:

要求為Number類型的參數(shù),設(shè)置請(qǐng)求超時(shí)時(shí)間(毫秒)。此設(shè)置將覆蓋$.ajaxSetup()方法的全局設(shè)置。

(四)async:

要求為Boolean類型的參數(shù),默認(rèn)設(shè)置為true,所有請(qǐng)求均為異步請(qǐng)求。如果需要發(fā)送同步請(qǐng)求,請(qǐng)將此選項(xiàng)設(shè)置為false。注意,同步請(qǐng)求將鎖住瀏覽器,用戶其他操作必須等待請(qǐng)求完成才可以執(zhí)行。

(五)cache

要求為Boolean類型的參數(shù),默認(rèn)為true(當(dāng)dataType為script時(shí),默認(rèn)為false),設(shè)置為false將不會(huì)從瀏覽器緩存中加載請(qǐng)求信息。

(六)data:

要求為Object或String類型的參數(shù),發(fā)送到服務(wù)器的數(shù)據(jù)。如果已經(jīng)不是字符串,將自動(dòng)轉(zhuǎn)換為字符串格式。get請(qǐng)求中將附加在url后。防止這種自動(dòng)轉(zhuǎn)換,可以查看  processData選項(xiàng)。對(duì)象必須為key/value格式,例如{foo1:"bar1",foo2:"bar2"}轉(zhuǎn)換為&foo1=bar1&foo2=bar2。如果是數(shù)組,JQuery將自動(dòng)為不同值對(duì)應(yīng)同一個(gè)名稱。例如{foo:["bar1","bar2"]}轉(zhuǎn)換為&foo=bar1&foo=bar2。

(七)dataType:

要求為String類型的參數(shù),預(yù)期服務(wù)器返回的數(shù)據(jù)類型。如果不指定,JQuery將自動(dòng)根據(jù)http包mime信息返回responseXML或responseText,并作為回調(diào)函數(shù)參數(shù)傳遞??捎玫念愋腿缦拢?/h4>

xml:返回XML文檔,可用JQuery處理。

html:返回純文本HTML信息;包含的script標(biāo)簽會(huì)在插入DOM時(shí)執(zhí)行。

script:返回純文本JavaScript代碼。不會(huì)自動(dòng)緩存結(jié)果。除非設(shè)置了cache參數(shù)。注意在遠(yuǎn)程請(qǐng)求時(shí)(不在同一個(gè)域下),所有post請(qǐng)求都將轉(zhuǎn)為get請(qǐng)求。

json:返回JSON數(shù)據(jù)。

jsonp:JSONP格式。使用SONP形式調(diào)用函數(shù)時(shí),例如myurl?callback=?,JQuery將自動(dòng)替換后一個(gè)“?”為正確的函數(shù)名,以執(zhí)行回調(diào)函數(shù)。

text:返回純文本字符串。

(八)beforeSend:

要求為Function類型的參數(shù),發(fā)送請(qǐng)求前可以修改XMLHttpRequest對(duì)象的函數(shù),例如添加自定義HTTP頭。在beforeSend中如果返回false可以取消本次ajax請(qǐng)求。XMLHttpRequest對(duì)象是惟一的參數(shù)。

function(XMLHttpRequest){
      this;   //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
 }

(九)complete:

要求為Function類型的參數(shù),請(qǐng)求完成后調(diào)用的回調(diào)函數(shù)(請(qǐng)求成功或失敗時(shí)均調(diào)用)。參數(shù):XMLHttpRequest對(duì)象和一個(gè)描述成功請(qǐng)求類型的字符串。

 function(XMLHttpRequest, textStatus){
        this;    //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
  }

(十)success:

要求為Function類型的參數(shù),請(qǐng)求成功后調(diào)用的回調(diào)函數(shù),有兩個(gè)參數(shù)。

(1)由服務(wù)器返回,并根據(jù)dataType參數(shù)進(jìn)行處理后的數(shù)據(jù)。

(2)描述狀態(tài)的字符串。

 function(data, textStatus){
            //data可能是xmlDoc、jsonObj、html、text等等
            this;  //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
         }

(十一)error:

要求為Function類型的參數(shù),請(qǐng)求失敗時(shí)被調(diào)用的函數(shù)。該函數(shù)有3個(gè)參數(shù),即XMLHttpRequest對(duì)象、錯(cuò)誤信息、捕獲的錯(cuò)誤對(duì)象(可選)。ajax事件函數(shù)如下:

  function(XMLHttpRequest, textStatus, errorThrown){
          //通常情況下textStatus和errorThrown只有其中一個(gè)包含信息
          this;   //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
       }

(十二)contentType:

要求為String類型的參數(shù),當(dāng)發(fā)送信息至服務(wù)器時(shí),內(nèi)容編碼類型默認(rèn)為"application/x-www-form-urlencoded"。該默認(rèn)值適合大多數(shù)應(yīng)用場合。

(十三)dataFilter:

要求為Function類型的參數(shù),給Ajax返回的原始數(shù)據(jù)進(jìn)行預(yù)處理的函數(shù)。提供data和type兩個(gè)參數(shù)。data是Ajax返回的原始數(shù)據(jù),type是調(diào)用jQuery.ajax時(shí)提供的dataType參數(shù)。函數(shù)返回的值將由jQuery進(jìn)一步處理。

 function(data, type){
                //返回處理后的數(shù)據(jù)
                return data;
            }

(十四)global:

要求為Boolean類型的參數(shù),默認(rèn)為true。表示是否觸發(fā)全局ajax事件。設(shè)置為false將不會(huì)觸發(fā)全局ajax事件,ajaxStart或ajaxStop可用于控制各種ajax事件。

(十五)ifModified:

要求為Boolean類型的參數(shù),默認(rèn)為false。僅在服務(wù)器數(shù)據(jù)改變時(shí)獲取新數(shù)據(jù)。服務(wù)器數(shù)據(jù)改變判斷的依據(jù)是Last-Modified頭信息。默認(rèn)值是false,即忽略頭信息。

(十六)jsonp:

要求為String類型的參數(shù),在一個(gè)jsonp請(qǐng)求中重寫回調(diào)函數(shù)的名字。該值用來替代在"callback=?"這種GET或POST請(qǐng)求中URL參數(shù)里的"callback"部分,例如{jsonp:'onJsonPLoad'}會(huì)導(dǎo)致將"onJsonPLoad=?"傳給服務(wù)器。

(十七)username:

要求為String類型的參數(shù),用于響應(yīng)HTTP訪問認(rèn)證請(qǐng)求的用戶名。

(十八)password:

要求為String類型的參數(shù),用于響應(yīng)HTTP訪問認(rèn)證請(qǐng)求的密碼。

(十九)processData:

要求為Boolean類型的參數(shù),默認(rèn)為true。默認(rèn)情況下,發(fā)送的數(shù)據(jù)將被轉(zhuǎn)換為對(duì)象(從技術(shù)角度來講并非字符串)以配合默認(rèn)內(nèi)容類型"application/x-www-form-urlencoded"。如果要發(fā)送DOM樹信息或者其他不希望轉(zhuǎn)換的信息,請(qǐng)?jiān)O(shè)置為false。

(二十)scriptCharset:

要求為String類型的參數(shù),只有當(dāng)請(qǐng)求時(shí)dataType為"jsonp"或者"script",并且type是GET時(shí)才會(huì)用于強(qiáng)制修改字符集(charset)。通常在本地和遠(yuǎn)程的內(nèi)容編碼不同時(shí)使用。

(二十一)$.each()函數(shù):

$.each()函數(shù)不同于JQuery對(duì)象的each()方法,它是一個(gè)全局函數(shù),不操作JQuery對(duì)象,而是以一個(gè)數(shù)組或者對(duì)象作為第1個(gè)參數(shù),以一個(gè)回調(diào)函數(shù)作為第2個(gè)參數(shù)?;卣{(diào)函數(shù)擁有兩個(gè)參數(shù):第1個(gè)為對(duì)象的成員或數(shù)組的索引,第2個(gè)為對(duì)應(yīng)變量或內(nèi)容。

(4)涉及的重要對(duì)象:

(一)XMLHTTPRequest對(duì)象:(Ajax獨(dú)有)

Ajax的一個(gè)最大的特點(diǎn)是無需刷新頁面便可向服務(wù)器傳輸或讀寫數(shù)據(jù)(又稱無刷新更新頁面),這一特點(diǎn)主要得益于XMLHTTP組件XMLHTTPRequest對(duì)象。

方 法 描述
abort() 停止當(dāng)前請(qǐng)求
getAllResponseHeaders() 把HTTP請(qǐng)求的所有響應(yīng)首部作為鍵/值對(duì)返回
getResponseHeader("header") 返回指定首部的串值
open("method","URL",[asyncFlag],["userName"],["password"]) 建立對(duì)服務(wù)器的調(diào)用。method參數(shù)可以是GET、POST或PUT。url參數(shù)可以是相對(duì)URL或絕對(duì)URL。這個(gè)方法還包括3個(gè)可選的參數(shù),是否異步,用戶名,密碼
send(content) 向服務(wù)器發(fā)送請(qǐng)求
setRequestHeader("header", "value") 把指定首部設(shè)置為所提供的值。在設(shè)置任何首部之前必須先調(diào)用open()。設(shè)置header并和請(qǐng)求一起發(fā)送 ('post'方法一定要 )
----- ----

XMLHttpRequest 對(duì)象屬性描述

屬 性 描 述
onreadystatechange 狀態(tài)改變的事件觸發(fā)器,每個(gè)狀態(tài)改變時(shí)都會(huì)觸發(fā)這個(gè)事件處理器,通常會(huì)調(diào)用一個(gè)JavaScript函數(shù)
readyState 請(qǐng)求的狀態(tài)。有5個(gè)可取值:0 = 未初始化,1 = 正在加載,2 = 已加載,3 = 交互中,4 = 完成
responseText 服務(wù)器的響應(yīng),返回?cái)?shù)據(jù)的文本。
responseXML 服務(wù)器的響應(yīng),返回?cái)?shù)據(jù)的兼容DOM的XML文檔對(duì)象 ,這個(gè)對(duì)象可以解析為一個(gè)DOM對(duì)象。
responseBody 服務(wù)器返回的主題(非文本格式)
responseStream 服務(wù)器返回的數(shù)據(jù)流
status 服務(wù)器的HTTP狀態(tài)碼(如:404 = "文件末找到" 、200 ="成功" ,等等)
statusText 服務(wù)器返回的狀態(tài)文本信息 ,HTTP狀態(tài)碼的相應(yīng)文本(OK或Not Found(未找到)等等)

(二)DOM Document Object Model

DOM是給HTML和XML文件使用的一組API。它提供了文件的結(jié)構(gòu)表述,讓你可以改變其中的內(nèi)容及可見物。其本質(zhì)是建立網(wǎng)頁與Script或程序語言溝通的橋梁。所有WEB開發(fā)人員可操作及建立文件的屬性、方法及事件都以對(duì)象來展現(xiàn)(例如,document就代表“文件本身“這個(gè)對(duì)像,table對(duì)象則代表HTML的表格對(duì)象等等)。這些對(duì)象可以由當(dāng)今大多數(shù)的瀏覽器以Script來取用。一個(gè)用HTML或XHTML構(gòu)建的網(wǎng)頁也可以看作是一組結(jié)構(gòu)化的數(shù)據(jù),這些數(shù)據(jù)被封在DOM(Document Object Model)中,DOM提供了網(wǎng)頁中各個(gè)對(duì)象的讀寫的支持。


二、企業(yè)級(jí)報(bào)表Excel導(dǎo)入導(dǎo)出:

(1)Excel報(bào)表導(dǎo)出:

實(shí)現(xiàn):

(一)MAVEN對(duì)應(yīng)的庫先:POI、還有文件上傳的包:

 <!--文件上傳-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.2.1</version>
    </dependency>

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>1.4</version>
    </dependency>
    
 <!-- POI -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.15</version>
    </dependency>

    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.15</version>
    </dependency>

(二)制作Excel樣式:

創(chuàng)建個(gè)Excel文件,定義自己喜歡的顏色字體,,,就這么簡單:

這里寫圖片描述

然后:另存為xls格式或者xlsx格式

這里寫圖片描述

(三)打開那個(gè)滿是xml代碼的文件復(fù)制到我們的jsp中

這里寫圖片描述

到j(luò)sp文件中:doExcel.jsp

至于數(shù)據(jù)如何接入??看下注釋吧。而且!??!我們只需要在兩部分寫入數(shù)據(jù)解析代碼,其余不要?jiǎng)樱?/h4>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.*"%>
<%@ page import="com.fuzhu.entity.GoodDetails" %>
<%
//首先看到我們上面導(dǎo)入的java包。然后在這里拿到后臺(tái)傳過來的list
    String titleName = "商品列表";

    response.addHeader("Content-disposition", "attachment;filename=" + (new String(titleName.getBytes("GBK"), "iso-8859-1")) + ".xls");
    //拿到數(shù)據(jù)
    List<String> headList=(List)request.getAttribute("headList");
    List<GoodDetails> dataList=(List)request.getAttribute("resultList");
%>

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
          xmlns:o="urn:schemas-microsoft-com:office:office"
          xmlns:x="urn:schemas-microsoft-com:office:excel"
          xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
          xmlns:html="http://www.w3.org/TR/REC-html40">
    <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
        <Created>2006-09-13T11:21:51Z</Created>
        <LastSaved>2011-10-20T11:56:16Z</LastSaved>
        <Version>12.00</Version>
    </DocumentProperties>
    <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
        <RemovePersonalInformation/>
    </OfficeDocumentSettings>
    <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
        <WindowHeight>11640</WindowHeight>
        <WindowWidth>19200</WindowWidth>
        <WindowTopX>0</WindowTopX>
        <WindowTopY>90</WindowTopY>
        <ProtectStructure>False</ProtectStructure>
        <ProtectWindows>False</ProtectWindows>
    </ExcelWorkbook>
    <Styles>
        <Style ss:ID="Default" ss:Name="Normal">
            <Alignment ss:Vertical="Center"/>
            <Borders/>
            <Font ss:FontName="宋體" x:CharSet="134" ss:Size="11" ss:Color="#000000"/>
            <Interior/>
            <NumberFormat/>
            <Protection/>
        </Style>
        <Style ss:ID="s66" ss:Name="常規(guī) 2 2 2">
            <Font ss:FontName="宋體" x:CharSet="134" ss:Size="12"/>
        </Style>
        <Style ss:ID="s62">
            <Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
        </Style>
        <Style ss:ID="s67" ss:Parent="s66">
            <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
            <Borders>
             <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            </Borders>
              <Font ss:FontName="宋體" x:CharSet="134" ss:Color="#FFFFFF" ss:Bold="1"/>
            <Interior ss:Color="#0066CC" ss:Pattern="Solid"/>
        </Style>
        <Style ss:ID="s68">
            <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
            <Borders>
             <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"
            ss:Color="#000000"/>
            </Borders>
              <Font ss:FontName="宋體" x:CharSet="134" ss:Size="9"/>
            <Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
        </Style>
    </Styles>
    <!-- 文件名字-->
    <Worksheet ss:Name="商品列表">
        <Table ss:ExpandedColumnCount="<%=headList.size() %>" ss:ExpandedRowCount="65000" x:FullColumns="1"
               x:FullRows="1" ss:DefaultColumnWidth="99" ss:DefaultRowHeight="20.0625">
            <Row ss:AutoFitHeight="0" ss:Height="33.75">
                <%
                //看到Row沒有,就是行的意思,我們要自建循環(huán)去遍歷我們拿到的數(shù)據(jù)。我們先遍歷頭部(頂欄一般有說明的嘛),然后再去遍歷數(shù)據(jù)欄
                    for(int i=0;i<headList.size();i++){
                %>
                <Cell ss:StyleID="s67"><Data ss:Type="String"><%=headList.get(i) %></Data></Cell>
                <%
                    }
                %>

            </Row>

            <%
            //遍歷數(shù)據(jù)欄
                for(int x=0;x<dataList.size();x++){

            %>
            <Row ss:AutoFitHeight="0">
                <Cell ss:StyleID="s68"><Data ss:Type="String"><%=dataList.get(x).getGoodName()==null?"":dataList.get(x).getGoodName()%></Data></Cell>
                <Cell ss:StyleID="s68"><Data ss:Type="String"><%=dataList.get(x).getGoodBrand()==null?"":dataList.get(x).getGoodBrand()%></Data></Cell>
                <Cell ss:StyleID="s68"><Data ss:Type="String"><%=dataList.get(x).getStoreAdd()==null?"":dataList.get(x).getStoreAdd()%></Data></Cell>
                <Cell ss:StyleID="s68"><Data ss:Type="String"><%=dataList.get(x).getSellerCredit()==null?"":dataList.get(x).getSellerCredit()%></Data></Cell>
                <Cell ss:StyleID="s68"><Data ss:Type="String"><%=dataList.get(x).getGoodPrice()==null?"":dataList.get(x).getGoodPrice()%></Data></Cell>
            </Row>
            <%
                }
            %>
        </Table>
        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
            <PageSetup>
                <Header x:Margin="0.3"/>
                <Footer x:Margin="0.3"/>
                <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
            </PageSetup>
            <Unsynced/>
            <Print>
                <ValidPrinterInfo/>
                <PaperSizeIndex>9</PaperSizeIndex>
                <HorizontalResolution>200</HorizontalResolution>
                <VerticalResolution>200</VerticalResolution>
            </Print>
            <Selected/>
            <Panes>
                <Pane>
                    <Number>3</Number>
                    <ActiveRow>1</ActiveRow>
                </Pane>
            </Panes>
            <ProtectObjects>False</ProtectObjects>
            <ProtectScenarios>False</ProtectScenarios>
        </WorksheetOptions>
    </Worksheet>
</Workbook>

(四)傳給用戶的Excel文件寫完了,我們要怎樣在后臺(tái)交接數(shù)據(jù)呢??

@RequestMapping(value = "/getExcel",produces="text/html;charset=UTF-8", method = {RequestMethod.GET,RequestMethod.POST})
    public String getExcel(HttpServletRequest request){
        String location ="";
        List<GoodDetails>  goodlist =  goodService.getGoodList(location);//查出數(shù)據(jù)
        request.setAttribute("resultList",goodlist);
        List<String> headList = new ArrayList<>();//頂欄的list
        headList.add("商品名");
        headList.add("商品類型");
        headList.add("商品地址");
        headList.add("商品星級(jí)");
        headList.add("商品價(jià)格");
        request.setAttribute("headList",headList);
        return "doExcel";
    }

這是前端點(diǎn)擊的下載按鈕。

這里寫圖片描述
  <div style="width:100%;text-align:center">
        <button><a href="getExcel">下載商品列表</a></button>
    </div>

(2)Excel報(bào)表導(dǎo)入:

(一)給出我們的規(guī)范:讓用戶下載(博主順手做多了兩份模板,就給大家用啦,哈哈,見下方源碼)

這里寫圖片描述

(二)留出我們的導(dǎo)入接口:

前端:

<div>
    <form id="formItem" method="post" action="uploadExcel"   enctype="multipart/form-data">
        <div id="fileArea"
             style="text-align: left; margin: 10px 10px 10px 20px;">
            <p>
                <label>選擇導(dǎo)入文件:</label>
                <input type="file" id="filename" name="filename" />
            </p>
            <input type="button" name="upload" id="upload" value="導(dǎo)入數(shù)據(jù)" onclick="doLoadTask()">

        </div>
    </form>

</div>

<div id="manualHelpTable"
     style="text-align: left; margin-left: 20px;">
    <table>
        <tbody style="vertical-align: top;">
        <tr>
            <td style="white-space:nowrap;">文件類型:</td>
            <td>
                .xls或.xlsx電子表格文件 (1.表格中不需要留空行; 2.文件名的后綴必須是小寫的".xls"或".xlsx";)
            </td>
        </tr>
        <tr>
            <td style="white-space:nowrap;">備注:</td>
            <td>
                <pre>導(dǎo)入支持新增,暫不支持修改數(shù)據(jù),僅支持商品數(shù)據(jù)導(dǎo)入</pre>
            </td>
        </tr>
        <tr>
            <td style="white-space:nowrap;">導(dǎo)入模板:</td>
            <td style="color: blue;">
                <a href="../../source/plan.xls">商品表導(dǎo)入模板.xls</a>&nbsp;&nbsp;&nbsp;
                <a href="../../source/plan.xls">商品表導(dǎo)入模板.xlsx</a>
            </td>
        </tr>

        </tbody>
    </table>
</div>

(三)利用js寫好上傳函數(shù)--檢查文件表層規(guī)范(后綴、大小等等)、導(dǎo)入步驟:

function doLoadTask() {
        var file = $("#filename").val();
        if (file == '') {
            alert("請(qǐng)選擇待處理文件");
            return;
        } else {
            //獲取文件類型后綴
            var temp = file.substring(file.lastIndexOf("\\") + 1).toString();
//            alert(temp)
            var extend = file.substring(file.lastIndexOf(".") + 1).toString();
//            alert(extend)
            if (extend == "") {
                alert("請(qǐng)選擇正確格式的文件!");
                return;
            } else {
                if (!(extend == "xlsx") && !(extend == "xls")) {
                    alert("請(qǐng)選擇正確格式的文件!");
                    return;
                }
            }
        }

//        var form = document.getElementById("formItem");
        $("#formItem").submit();
    }

(四)后端接收用戶上傳的文件:controller層

    @Autowired
    private ParseExcel parseExcel;


 @RequestMapping(value = "/uploadExcel",produces="text/html;charset=UTF-8", method = {RequestMethod.GET,RequestMethod.POST})
    public String uploadExcel(HttpServletRequest request ,@RequestParam(value = "filename", required = false) MultipartFile file){
        String path = request.getSession().getServletContext().getRealPath("uploadExcel");
        String fileName = file.getOriginalFilename();//拿到文件名
        System.out.println(path);
        File targetFile = new File(path, fileName);//存儲(chǔ)的目錄名
        System.out.println(targetFile);
        System.out.println(targetFile.toString());
        if(!targetFile.exists()){
            targetFile.mkdirs();//不存在目錄就創(chuàng)建咯
        }
        //保存
        try {
            file.transferTo(targetFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<GoodDetails> list = null;//拿到我們導(dǎo)入的list后就是往數(shù)據(jù)庫批量插入了,這個(gè)就太簡單了,我就不寫了。
        if(fileName.endsWith(".xls")||fileName.endsWith(".xlsx")) {
            list = parseExcel.parseExcel((File) targetFile, targetFile.toString());
        }
        return "success";
    }

(五)接收的文件后,想要導(dǎo)入到數(shù)據(jù)庫的前提還有一對(duì)一的數(shù)據(jù)檢驗(yàn)以及數(shù)據(jù)獲取,然后才可用對(duì)象存儲(chǔ)方式寫入數(shù)據(jù)庫

//定義解析接口
public interface ParseExcel {
    List<GoodDetails> parseExcel(File xlsFile,String filename);
}

一對(duì)一的數(shù)據(jù)獲取與校驗(yàn)

@Service
public class ParseExcelImpl implements ParseExcel {
    @Override
    public List<GoodDetails> parseExcel(File xlsFile, String filename) {
        boolean isE2007 = false;    //判斷是否是excel2007格式
        if (filename.endsWith("xlsx"))
            isE2007 = true;
        System.out.println(isE2007);

        List<GoodDetails> goodDetailsList = new ArrayList<>();
        try {
            InputStream input = new FileInputStream(filename);  //建立輸入流
            Workbook wb = null;
            //根據(jù)文件格式(2003或者2007)來初始化
            if (isE2007)
                wb = new XSSFWorkbook(input);//xlsx后綴
            else
                wb = new HSSFWorkbook(input);//xls后綴

            System.out.println(wb);
            Sheet sheet = wb.getSheetAt(0);     //獲得第一個(gè)表單

            Iterator<Row> rows = sheet.rowIterator(); //獲得第一個(gè)表單的迭代器
            while (rows.hasNext()) {//遍歷每一行

                Row row = rows.next();  //獲得行數(shù)據(jù)
                System.out.println("Row #" + row.getRowNum());  //獲得行號(hào)從0開始
                Iterator<Cell> cells = row.cellIterator();    //獲得第一行的迭代器

                GoodDetails goodDetails = null;
                if (row.getRowNum() > 0) {
                    goodDetails = new GoodDetails();  //每行一條記錄嘛
                    System.out.println("第幾行   " + row.getRowNum());
                }
                while (cells.hasNext()) {//在每一行基礎(chǔ)上去遍歷每一列
                    Cell cell = cells.next();//指向下一列
                    int i = cell.getColumnIndex();//拿到列的標(biāo)記
                    System.out.println("Cell #" + cell.getColumnIndex());

                    if (goodDetails != null) {
                        switch (i) {//針對(duì)列去獲取解析,放進(jìn)我們的java對(duì)象
                            case 0:
                                goodDetails.setGoodName(String.valueOf(cell.getStringCellValue()));
                                break;
                            case 1:
                                goodDetails.setGoodBrand(String.valueOf(cell.getStringCellValue()));
                                break;
                            case 2:
                                goodDetails.setStoreAdd(String.valueOf(cell.getStringCellValue()));
                                break;
                            case 3:
                                goodDetails.setSellerCredit(String.valueOf(cell.getStringCellValue()));
                                break;
                            case 4:
                                goodDetails.setGoodPrice(String.valueOf(cell.getNumericCellValue()));
                                break;
                            default:
                                System.out.println("unsuported sell type");
                                break;
                        }
                    }

//下面這段注釋代碼,給大家認(rèn)識(shí)下每一列對(duì)應(yīng)的數(shù)據(jù)類型:

//                    switch (cell.getCellType()) {   //根據(jù)cell中的類型來輸出數(shù)據(jù)
//                        case HSSFCell.CELL_TYPE_NUMERIC: //讀取數(shù)字
//                            //先看是否是日期格式
//                            if(HSSFDateUtil.isCellDateFormatted(cell)){
//                                //讀取日期格式
//                                System.out.print("一   "+cell.getDateCellValue()+" ");
//                            }else{
//                                //讀取數(shù)字
//                                System.out.print("一   "+cell.getNumericCellValue()+" ");
//                                if (goodDetails!=null){
//                                    goodDetails.setGoodPrice(String.valueOf(cell.getNumericCellValue()));
//                                }
//
//                            }
//                            break;
//                        case HSSFCell.CELL_TYPE_STRING://讀取文本對(duì)象
//                            System.out.println("二   "+cell.getStringCellValue());
//
//                            break;
//                        case HSSFCell.CELL_TYPE_BOOLEAN:  //得到Boolean對(duì)象的方法
//                            System.out.println("三   "+cell.getBooleanCellValue());
//                            break;
//                        case HSSFCell.CELL_TYPE_FORMULA://得到公式
//                            System.out.println("四   "+cell.getCellFormula());
//                            break;
//                        default:
//                            System.out.println("unsuported sell type");
//                            break;
//                    }
                }
                goodDetailsList.add(goodDetails);//拿到我們導(dǎo)入的list后就是往數(shù)據(jù)庫批量插入了,這個(gè)就太簡單了,我就不寫了。
            }
            System.out.println(goodDetailsList.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return goodDetailsList;
    }
}

然后??下載文件,對(duì)著格式輸入,然后上傳

這里寫圖片描述
## 源碼下載:[J2EE項(xiàng)目系列(四)--SSM框架構(gòu)建積分系統(tǒng)和基本商品檢索系統(tǒng)(Spring+SpringMVC+MyBatis)(3)Ajax使用詳解(級(jí)聯(lián)列表)以及企業(yè)級(jí)報(bào)表Excel導(dǎo)入導(dǎo)出實(shí)現(xiàn)](https://github.com/FuZhucheng/SSM)
### 好了,J2EE項(xiàng)目系列(四)--SSM框架構(gòu)建積分系統(tǒng)和基本商品檢索系統(tǒng)(Spring+SpringMVC+MyBatis)(3)Ajax使用詳解(級(jí)聯(lián)列表)以及企業(yè)級(jí)報(bào)表Excel導(dǎo)入導(dǎo)出實(shí)現(xiàn)講完了,這是實(shí)習(xí)時(shí)候所學(xué)到的一些功能點(diǎn),在這里寫出來記錄,這是積累的必經(jīng)一步,我會(huì)繼續(xù)出這個(gè)系列文章,分享經(jīng)驗(yàn)給大家。歡迎在下面指出錯(cuò)誤,共同學(xué)習(xí)??!你的點(diǎn)贊是對(duì)我最好的支持!!

###  更多內(nèi)容,可以訪問[JackFrost的博客](http://blog.csdn.net/jack__frost?viewmode=contents)                 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • AJAX 原生js操作ajax 1.創(chuàng)建XMLHttpRequest對(duì)象 var xhr = new XMLHtt...
    碧玉含香閱讀 3,563評(píng)論 0 7
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 12,417評(píng)論 6 13
  • 本文詳細(xì)介紹了 XMLHttpRequest 相關(guān)知識(shí),涉及內(nèi)容: AJAX、XMLHTTP、XMLHttpReq...
    semlinker閱讀 13,996評(píng)論 2 18
  • 五十三:請(qǐng)解釋 JavaScript 中 this 是如何工作的。1.方法調(diào)用模式當(dāng)一個(gè)函數(shù)被保存為一個(gè)對(duì)象的屬性...
    Arno_z閱讀 683評(píng)論 0 2
  • 你可以 撕毀我的文章 燒掉我的衣裳 你可以 讓我遍體鱗傷 甚至死亡 但是你用永遠(yuǎn) 也別妄想 毀掉我的學(xué)識(shí) 攫取我的...
    文展閱讀 302評(píng)論 13 2

友情鏈接更多精彩內(nèi)容