J2EE项目系列(四)--SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis)(3)Ajax使用详解(级联列表)以及企业级报表Excel导入导出实现

来源:互联网 发布:vivo一键锁屏软件 编辑:程序博客网 时间:2024/05/21 19:30

今天来讲下企业的开发的一些功能应用吧,就是Ajax使用,以及简单的企业报表的导入导出,基于原有的项目进行展示(其实是本博主想偷懒)。

本系列:

(一)项目框架整合构建

(二)建立商品数据库和Lucene的搭建

(三) Redis系列(一)–安装、helloworld以及读懂配置文件

(四)Redis系列(二)–缓存设计(整表缓存以及排行榜缓存方案实现)

(五) Lucene总结系列(一)–认识、helloworld以及基本的api操作。

(六)Lucene总结系列(二)–商品检索系统的文字检索业务(lucene项目使用)

(七)Lucene总结系列(三)–总述优化方案和呈现实时内存索引实现(结合RAMDirectory源码解析)

(八)JavaWeb–Servlet过滤器Filter和SpringMVC的HandlerInterceptor(Session和Cookie登录认证)

(九)Redis系列(三)–过期策略

(十)Redis系列(四)–内存淘汰机制(含单机版内存优化建议)


文章结构:(1)Ajax使用详解(级联列表例子);(2)企业级报表Excel导入导出;

一、Ajax使用详解(级联列表例子):

(1)概述:

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

应用:

运用XHTML+CSS来表达资讯;
运用JavaScript操作DOM(Document Object Model)来执行动态效果;
运用XML和XSLT操作资料;
运用XMLHttpRequest或新的Fetch API与网页服务器进行异步资料交换;
注意:AJAX与Flash、Silverlight和Java Applet等RIA技术是有区分的。

不适用:

部分简单的表单
搜索
基本的导航
替换大量的文本
.对呈现的操纵

缺点:转载自此

1. AJAX干掉了Back和History功能,即对浏览器机制的破坏。在动态更新页面的情况下,用户无法回到前一个页面状态,因为浏览器仅能记忆历史记录中的静态页面。
2. AJAX的安全问题。
AJAX技术给用户带来很好的用户体验的同时也对IT企业带来了新的安全威胁,Ajax技术就如同对企业数据建立了一个直接通道。这使得开发者在不经意间会暴露比以前更多的数据和服务器逻辑。Ajax的逻辑可以对客户端的安全扫描技术隐藏起来,允许黑客从远端服务器上建立新的攻击。还有Ajax也难以避免一些已知的安全弱点,诸如跨站点脚步攻击、SQL注入攻击和基于Credentials的安全漏洞等等。
3. 对搜索引擎支持较弱:
对搜索引擎的支持比较弱。如果使用不当,AJAX会增大网络数据的流量,从而降低整个系统的性能。
4. 违背URL和资源定位的初衷。
例如,我给你一个URL地址,如果采用了Ajax技术,也许你在该URL地址下面看到的和我在这个URL地址下看到的内容是不同的。这个和资源定位的初衷是相背离的。
5. 客户端过肥,太多客户端代码造成开发上的成本。
编写复杂、容易出错 ;冗余代码比较多(层层包含js文件是AJAX的通病,再加上以往的很多服务端代码现在放到了客户端);破坏了Web的原有标准。

简单描述工作原理

Ajax的工作原理相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
Ajax其核心有JavaScript、XMLHTTPRequest、DOM对象组成,通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。让我们来了解这几个对象。

最基本的例子:

<!DOCTYPE html><html><head><meta charset="utf-8"><div id="myDiv"><h2> AJAX  HelloWorld</h2></div><button type="button" onclick="loadXMLDoc()">修改内容</button></script></head><body>
<script>function loadXMLDoc(){    //在里面去使用ajax做请求,以及更新前端UI    var xmlhttp;    if (window.XMLHttpRequest){        //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码        xmlhttp=new XMLHttpRequest();    }    else{        // IE6, IE5 浏览器执行代码        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");    }    xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);    xmlhttp.send();}</script>

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

这里写图片描述

(2)级联表实现:

描述:
就是在不更新页面情况下:商品地址,会更新下面所说的对应账号(博主为了偷懒,简单写的逻辑)。
图片展示:

这里写图片描述这里写图片描述

功能展示:选择广东省或北京市后:账号自动更新

这里写图片描述

实现:demo代码

(一)前端代码:

//注意我给select添加了一个监听喔。<div class="modal">        <p>            <label>商品地址:</label>            <select name="location" id="location" onchange="locationChange()">                <option value="">请选择</option>                <option value="广东省">广东省</option>                <option value="北京市">北京市</option>            </select>        </p>        <p>            <label>列出对应的账号:</label>            <select name="accounts" id="accounts">                <option value="">请选择</option>            </select>        </p>  </div>

(2)方法监听就看方法嘛:方法体详解在后面(下面的例子注释使用时请删去)

//$.ajax里面就是ajax的方法啦,动态加载:<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("请选择", ""));        $.ajax({            type: "post",     //请求类型            url: "/ajax/findUserByProvince",   //请求路径            cache: false,                   //缓存是否启用            data: {location: location},     //传参            dataType: "json",                //期望返回的数据体            success: function (result) {            //result是后台返回给前端的结果集,而我们上面期望他是一个json,所以就是个json数组咯                if (result.length > 0) {                    obj.add(new Option("请选择", ""));                    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);//这个只是一个简单的根据省份去查询用户账号的逻辑,想了解细节下方有源码下载        System.out.println(JSON.toJSONString(userList));        //返回一个json数组给前端        return JSON.toJSONString(userList);    }

补充:有朋友反应下面这个jQuery使用看不太懂

//$("#location")是绑定了id是location的标签组件//find("option:selected")是拿到上面的标签组件下面的option//使用text()就是可以拿到内容啦。var location = $("#location").find("option:selected").text();

这就是一个简单的级联列表实现,结合ajax。


(3)下面就详细讲解ajax方法体的各大参数吧:以下部分转载此博主此博客

(一)url:

要求为String类型的参数,(默认为当前页地址)发送请求的地址。

(二)type:

要求为String类型的参数,请求方式(post或get)默认为get。注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持。

(三)timeout:

要求为Number类型的参数,设置请求超时时间(毫秒)。此设置将覆盖$.ajaxSetup()方法的全局设置。

(四)async:

要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。

(五)cache

要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。

(六)data:

要求为Object或String类型的参数,发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。get请求中将附加在url后。防止这种自动转换,可以查看  processData选项。对象必须为key/value格式,例如{foo1:”bar1”,foo2:”bar2”}转换为&foo1=bar1&foo2=bar2。如果是数组,JQuery将自动为不同值对应同一个名称。例如{foo:[“bar1”,”bar2”]}转换为&foo=bar1&foo=bar2。

(七)dataType:

要求为String类型的参数,预期服务器返回的数据类型。如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。可用的类型如下:

xml:返回XML文档,可用JQuery处理。

html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。

script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。

json:返回JSON数据。

jsonp:JSONP格式。使用SONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。

text:返回纯文本字符串。

(八)beforeSend:

要求为Function类型的参数,发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。XMLHttpRequest对象是惟一的参数。

function(XMLHttpRequest){      this;   //调用本次ajax请求时传递的options参数 }

(九)complete:

要求为Function类型的参数,请求完成后调用的回调函数(请求成功或失败时均调用)。参数:XMLHttpRequest对象和一个描述成功请求类型的字符串。

 function(XMLHttpRequest, textStatus){        this;    //调用本次ajax请求时传递的options参数  }

(十)success:

要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。

(1)由服务器返回,并根据dataType参数进行处理后的数据。

(2)描述状态的字符串。

 function(data, textStatus){            //data可能是xmlDoc、jsonObj、html、text等等            this;  //调用本次ajax请求时传递的options参数         }

(十一)error:

要求为Function类型的参数,请求失败时被调用的函数。该函数有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。ajax事件函数如下:

  function(XMLHttpRequest, textStatus, errorThrown){          //通常情况下textStatus和errorThrown只有其中一个包含信息          this;   //调用本次ajax请求时传递的options参数       }

(十二)contentType:

要求为String类型的参数,当发送信息至服务器时,内容编码类型默认为”application/x-www-form-urlencoded”。该默认值适合大多数应用场合。

(十三)dataFilter:

要求为Function类型的参数,给Ajax返回的原始数据进行预处理的函数。提供data和type两个参数。data是Ajax返回的原始数据,type是调用jQuery.ajax时提供的dataType参数。函数返回的值将由jQuery进一步处理。

 function(data, type){                //返回处理后的数据                return data;            }

(十四)global:

要求为Boolean类型的参数,默认为true。表示是否触发全局ajax事件。设置为false将不会触发全局ajax事件,ajaxStart或ajaxStop可用于控制各种ajax事件。

(十五)ifModified:

要求为Boolean类型的参数,默认为false。仅在服务器数据改变时获取新数据。服务器数据改变判断的依据是Last-Modified头信息。默认值是false,即忽略头信息。

(十六)jsonp:

要求为String类型的参数,在一个jsonp请求中重写回调函数的名字。该值用来替代在”callback=?”这种GET或POST请求中URL参数里的”callback”部分,例如{jsonp:’onJsonPLoad’}会导致将”onJsonPLoad=?”传给服务器。

(十七)username:

要求为String类型的参数,用于响应HTTP访问认证请求的用户名。

(十八)password:

要求为String类型的参数,用于响应HTTP访问认证请求的密码。

(十九)processData:

要求为Boolean类型的参数,默认为true。默认情况下,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型”application/x-www-form-urlencoded”。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。

(二十)scriptCharset:

要求为String类型的参数,只有当请求时dataType为”jsonp”或者”script”,并且type是GET时才会用于强制修改字符集(charset)。通常在本地和远程的内容编码不同时使用。

(二十一)$.each()函数:

$.each()函数不同于JQuery对象的each()方法,它是一个全局函数,不操作JQuery对象,而是以一个数组或者对象作为第1个参数,以一个回调函数作为第2个参数。回调函数拥有两个参数:第1个为对象的成员或数组的索引,第2个为对应变量或内容。

(4)涉及的重要对象:

(一)XMLHTTPRequest对象:(Ajax独有)

Ajax的一个最大的特点是无需刷新页面便可向服务器传输或读写数据(又称无刷新更新页面),这一特点主要得益于XMLHTTP组件XMLHTTPRequest对象。

方 法 描述 abort() 停止当前请求 getAllResponseHeaders() 把HTTP请求的所有响应首部作为键/值对返回 getResponseHeader(“header”) 返回指定首部的串值 open(“method”,”URL”,[asyncFlag],[“userName”],[“password”]) 建立对服务器的调用。method参数可以是GET、POST或PUT。url参数可以是相对URL或绝对URL。这个方法还包括3个可选的参数,是否异步,用户名,密码 send(content) 向服务器发送请求 setRequestHeader(“header”, “value”) 把指定首部设置为所提供的值。在设置任何首部之前必须先调用open()。设置header并和请求一起发送 (‘post’方法一定要 )

XMLHttpRequest 对象属性描述

属 性 描 述 onreadystatechange 状态改变的事件触发器,每个状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数 readyState 请求的状态。有5个可取值:0 = 未初始化,1 = 正在加载,2 = 已加载,3 = 交互中,4 = 完成 responseText 服务器的响应,返回数据的文本。 responseXML 服务器的响应,返回数据的兼容DOM的XML文档对象 ,这个对象可以解析为一个DOM对象。 responseBody 服务器返回的主题(非文本格式) responseStream 服务器返回的数据流 status 服务器的HTTP状态码(如:404 = “文件末找到” 、200 =”成功” ,等等) statusText 服务器返回的状态文本信息 ,HTTP状态码的相应文本(OK或Not Found(未找到)等等)

(二)DOM Document Object Model

DOM是给HTML和XML文件使用的一组API。它提供了文件的结构表述,让你可以改变其中的內容及可见物。其本质是建立网页与Script或程序语言沟通的桥梁。所有WEB开发人员可操作及建立文件的属性、方法及事件都以对象来展现(例如,document就代表“文件本身“这个对像,table对象则代表HTML的表格对象等等)。这些对象可以由当今大多数的浏览器以Script来取用。一个用HTML或XHTML构建的网页也可以看作是一组结构化的数据,这些数据被封在DOM(Document Object Model)中,DOM提供了网页中各个对象的读写的支持。


二、企业级报表Excel导入导出:

(1)Excel报表导出:

实现:

(一)MAVEN对应的库先: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样式:

创建个Excel文件,定义自己喜欢的颜色字体,,,就这么简单:

这里写图片描述

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

这里写图片描述

(三)打开那个满是xml代码的文件复制到我们的jsp中

这里写图片描述

到jsp文件中:doExcel.jsp

至于数据如何接入??看下注释吧。而且!!!我们只需要在两部分写入数据解析代码,其余不要动!

<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ page import="java.util.*"%><%@ page import="com.fuzhu.entity.GoodDetails" %><%//首先看到我们上面导入的java包。然后在这里拿到后台传过来的list    String titleName = "商品列表";    response.addHeader("Content-disposition", "attachment;filename=" + (new String(titleName.getBytes("GBK"), "iso-8859-1")) + ".xls");    //拿到数据    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="常规 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没有,就是行的意思,我们要自建循环去遍历我们拿到的数据。我们先遍历头部(顶栏一般有说明的嘛),然后再去遍历数据栏                    for(int i=0;i<headList.size();i++){                %>                <Cell ss:StyleID="s67"><Data ss:Type="String"><%=headList.get(i) %></Data></Cell>                <%                    }                %>            </Row>            <%            //遍历数据栏                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文件写完了,我们要怎样在后台交接数据呢??

@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);//查出数据        request.setAttribute("resultList",goodlist);        List<String> headList = new ArrayList<>();//顶栏的list        headList.add("商品名");        headList.add("商品类型");        headList.add("商品地址");        headList.add("商品星级");        headList.add("商品价格");        request.setAttribute("headList",headList);        return "doExcel";    }

这是前端点击的下载按钮。

这里写图片描述

  <div style="width:100%;text-align:center">        <button><a href="getExcel">下载商品列表</a></button>    </div>

(2)Excel报表导入:

(一)给出我们的规范:让用户下载(博主顺手做多了两份模板,就给大家用啦,哈哈,见下方源码)

这里写图片描述

(二)留出我们的导入接口:

前端:

<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>选择导入文件:</label>                <input type="file" id="filename" name="filename" />            </p>            <input type="button" name="upload" id="upload" value="导入数据" 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>导入支持新增,暂不支持修改数据,仅支持商品数据导入</pre>            </td>        </tr>        <tr>            <td style="white-space:nowrap;">导入模板:</td>            <td style="color: blue;">                <a href="../../source/plan.xls">商品表导入模板.xls</a>&nbsp;&nbsp;&nbsp;                <a href="../../source/plan.xls">商品表导入模板.xlsx</a>            </td>        </tr>        </tbody>    </table></div>

(三)利用js写好上传函数–检查文件表层规范(后缀、大小等等)、导入步骤:

function doLoadTask() {        var file = $("#filename").val();        if (file == '') {            alert("请选择待处理文件");            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("请选择正确格式的文件!");                return;            } else {                if (!(extend == "xlsx") && !(extend == "xls")) {                    alert("请选择正确格式的文件!");                    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);//存储的目录名        System.out.println(targetFile);        System.out.println(targetFile.toString());        if(!targetFile.exists()){            targetFile.mkdirs();//不存在目录就创建咯        }        //保存        try {            file.transferTo(targetFile);        } catch (Exception e) {            e.printStackTrace();        }        List<GoodDetails> list = null;//拿到我们导入的list后就是往数据库批量插入了,这个就太简单了,我就不写了。        if(fileName.endsWith(".xls")||fileName.endsWith(".xlsx")) {            list = parseExcel.parseExcel((File) targetFile, targetFile.toString());        }        return "success";    }

(五)接收的文件后,想要导入到数据库的前提还有一对一的数据检验以及数据获取,然后才可用对象存储方式写入数据库

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

一对一的数据获取与校验

@Servicepublic 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;            //根据文件格式(2003或者2007)来初始化            if (isE2007)                wb = new XSSFWorkbook(input);//xlsx后缀            else                wb = new HSSFWorkbook(input);//xls后缀            System.out.println(wb);            Sheet sheet = wb.getSheetAt(0);     //获得第一个表单            Iterator<Row> rows = sheet.rowIterator(); //获得第一个表单的迭代器            while (rows.hasNext()) {//遍历每一行                Row row = rows.next();  //获得行数据                System.out.println("Row #" + row.getRowNum());  //获得行号从0开始                Iterator<Cell> cells = row.cellIterator();    //获得第一行的迭代器                GoodDetails goodDetails = null;                if (row.getRowNum() > 0) {                    goodDetails = new GoodDetails();  //每行一条记录嘛                    System.out.println("第几行   " + row.getRowNum());                }                while (cells.hasNext()) {//在每一行基础上去遍历每一列                    Cell cell = cells.next();//指向下一列                    int i = cell.getColumnIndex();//拿到列的标记                    System.out.println("Cell #" + cell.getColumnIndex());                    if (goodDetails != null) {                        switch (i) {//针对列去获取解析,放进我们的java对象                            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;                        }                    }//下面这段注释代码,给大家认识下每一列对应的数据类型://                    switch (cell.getCellType()) {   //根据cell中的类型来输出数据//                        case HSSFCell.CELL_TYPE_NUMERIC: //读取数字//                            //先看是否是日期格式//                            if(HSSFDateUtil.isCellDateFormatted(cell)){//                                //读取日期格式//                                System.out.print("一   "+cell.getDateCellValue()+" ");//                            }else{//                                //读取数字//                                System.out.print("一   "+cell.getNumericCellValue()+" ");//                                if (goodDetails!=null){//                                    goodDetails.setGoodPrice(String.valueOf(cell.getNumericCellValue()));//                                }////                            }//                            break;//                        case HSSFCell.CELL_TYPE_STRING://读取文本对象//                            System.out.println("二   "+cell.getStringCellValue());////                            break;//                        case HSSFCell.CELL_TYPE_BOOLEAN:  //得到Boolean对象的方法//                            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);//拿到我们导入的list后就是往数据库批量插入了,这个就太简单了,我就不写了。            }            System.out.println(goodDetailsList.toString());        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        return goodDetailsList;    }}

然后??下载文件,对着格式输入,然后上传

这里写图片描述
“`

源码下载:J2EE项目系列(四)–SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis)(3)Ajax使用详解(级联列表)以及企业级报表Excel导入导出实现

好了,J2EE项目系列(四)–SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis)(3)Ajax使用详解(级联列表)以及企业级报表Excel导入导出实现讲完了,这是实习时候所学到的一些功能点,在这里写出来记录,这是积累的必经一步,我会继续出这个系列文章,分享经验给大家。欢迎在下面指出错误,共同学习!!你的点赞是对我最好的支持!!

更多内容,可以访问JackFrost的博客

阅读全文
5 0
原创粉丝点击