poi文件上传

来源:互联网 发布:windows10优化设置 编辑:程序博客网 时间:2024/05/07 17:38


1、  区域添加,修改

2、  区域 批量导入功能 (jquery ocupload 一键上传、 POI Excel文件解析pinyin4j工具包

3、  区域列表查询  (datagrid 分页 )

4、  区域的条件查询

 

1.  任务一: 基础设置模块 需求分析

参见 需求文档 2.6 基础档案

 

 

l  2.6.5 区域设置

        管理 物流业务所能覆盖行政区域(省、市、区… )

        行政区域信息 不可更改 !

 

l  2.6.6 管理分区

        举例: 你是一个快递员,让你负责上海闵行区快件配送 ---- 行政区域太大了,不能直接分配给快递员负责 ,将区域进行划分 ,成为分区

 

l  2.6.7 管理定区、调度排班

            区域、分区、定区几个概念的区别 ?

                 区域 ,行政区域,国家划分省、市、区

                 分区 ,因为区域很大,需要划分

                 (如果每个取派员负责一个分区,这样物流配送业务不够灵活

                 定区: 为几个取派员 划分到 几个分区的 负责 ,几个分区组成一个定区

2.  任务二: 区域信息批量导入功能

        导入功能 , 实现数据快速添加 --------- 上传数据文件

2.1. jquery ocupload (one-click)插件实现一键上传

回顾文件上传:

        客户端上传要求:

formenctype=”multipart/form-data” 采用多媒体表单数据编码

请求方式必须为post

<inputtype=”file” name="xxxxx"/> 文件框,提供name属性

服务器接受上传文件:

javaweb:apache commons-fileupload 工具包实现上传

struts2:  提供FileUploadInterceptor ,将commons-fileupload进行封装

    企业的系统,越来越多使用 一键上传

        好处: 页面只需要提供一个按钮或者链接,不需要上传浏览框

        一键上传功能,页面没有刷新,使用隐藏iframe模拟Ajax效果

一键上传编码:

第一步: 下载一键上传组件js

下载网址: http://code.google.com/p/ocupload 获得:jquery.ocupload-1.1.2.js

 Github : https://github.com/andreyfedoseev/jquery-ocupload

在bos项目引入ocupload.js

<!-- 一键上传 -->  region.jsp 页面导入脚本

可以对页面任何一个元素使用一键上传功能

 

在toolbar 导入按钮添加一键上传功能

根据 ocuploadoptions 设置一键上传属性 文档说明

l  上传文件采用excel文档上传

要求上传文件扩展名 .xls 或者 .xlsx

        上传框弹出后 -à选择文件后,不要立刻提交 autoSubmit 设置false ,在onSelect事件中进行文件扩展名的校验,满足文件格式要求后,再进行提交

可以参照下发资料代码模板完成!

 

   

测试 : 客户端一键上传js代码完成!

Js代码:

        $("#button-import").upload({

               name: 'upload',

               action: '${pageContext.request.contextPath}/regionAction_batchImport',

               enctype: 'multipart/form-data',

               onSelect: function (self, element) { 

                this.autoSubmit = false;  //  不要立刻提交上传文件

                var re =/^(.+\.xls|.+\.xlsx)$/;   // excel文件正则对象   xxx.xls  xxx.xlsx

                // this.filename() 获取当前上传文件名称

                if (re.test(this.filename())){ 

                         this.submit(); 

                } 

                else { 

                    $.messager.alert("警告!","必须上传excel文件","warning");

                } 

            },

            onComplete: function(data) {

                    //  data bool true   string true

                    alert(typeof(data));//string ---eval 转换 true

                    varflag = eval("("+data+")");//  "1"+"2"

                    if(flag){

                               $.messager.alert("恭喜!","上传成功","info");

                    }else{

                               $.messager.alert("遗憾!","上传失败","error");

            }

            }

        });

2.2. struts2 FileUpload Interceptor 接收上传文件

FileUploadIntercptor 就在 DefaultStack中,无需任何其它配置

源码:

编写RegionAction接收上传文件

        只需要在Action 中提供成员变量和setter方法,自动将上传文件设置进来

文档查看 完成开发excel解析

2.3. poi解析Excel 中数据

解析Excel ,生成Excel 常用开发组件 : Apache POI 、 JXL

        官网:http://poi.apache.org/

        企业最常用的是使用POI解析Excel,生成Excel !

        HSSF 解析 .xls格式(Excel 97- 2007前), XSSF 解析 .xlsx 格式 (Excel 2007 )

 

阅读 “POI3.5_HSSF_和XSSF_Excel操作快速入门手册.pdf”

参考 “POI整理.doc”

 

第一步: 在web项目引入POI , 使用maven坐标

<dependency>

                         <groupId>org.apache.poi</groupId>

                         <artifactId>poi</artifactId>

                         <version>${poi.version}</version>

                 </dependency>

                 <dependency>

                         <groupId>org.apache.poi</groupId>

                         <artifactId>poi-ooxml</artifactId>

                         <version>${poi.version}</version>

                 </dependency>

建议使用 3.9的版本

        <poi.version>3.9</poi.version>

 

第二步: 完善RegionAction的oneKeyUpload 方法

 

        POI解析 : Workbook 文件 ---- sheet 工作薄 ---- row 行 ---- cell 单元格

action代码如下  使用poi 读取struts2 上传文件!

步骤二 修改Region注解主键策略  因为区域表数据 主键由外部文件excel提供

编写Action业务方法解析excel文件

代码编写

  

Sheet 对象 forEach迭代

门面注入业务层对象

 

@Action(value ="regionAction_batchImport", results = { @Result(name ="batchImport", type = "json") })

        publicString batchImport() {

                 try{

                         //1`: poi解析 excel 工作簿--->sheet --->row--->cell--->value--->List<Region>

                         List<Region>regions = new ArrayList<Region>();

                         //创建对Excel工作簿文件的引用

                         HSSFWorkbookworkbook = new HSSFWorkbook(new FileInputStream(upload));

                         //创建对工作表的引用。

                         //本例是按名引用(让我们假定那张表有着缺省名"Sheet1")

                         //HSSFSheet sheet = workbook.getSheet("Sheet1");

                         //也可用getSheetAt(int index)按索引引用,

                         //在Excel文档中,第一张工作表的缺省索引是0,

                         //其语句为:HSSFSheet sheet = workbook.getSheetAt(0);

                         HSSFSheetsheet = workbook.getSheetAt(0);

                         //读取row

                         for(Row row : sheet) {

                                  //第一行数据 跳过

                                  if(row.getRowNum() == 0) {

                                          continue;

                                  }

                                  Regionregion = new Region();

                                  region.setId(row.getCell(0).getStringCellValue());

                                  region.setProvince(row.getCell(1).getStringCellValue());

                                  region.setCity(row.getCell(2).getStringCellValue());

                                  region.setDistrict(row.getCell(3).getStringCellValue());

                                  region.setPostcode(row.getCell(4).getStringCellValue());

                                  regions.add(region);

                         }

                         //2: list传递给 dao

                         facadeService.getRegionService().batchImport(regions);

                         push(true);

                 }catch (Exception e) {

                         push(false);

                         e.printStackTrace();

                 }

                 return"batchImport";

        }

第三步: 调用业务层,批量添加region

        DAO接口

 

第四步: 完善客户端回调函数

测试:

2.4. 区域生成区域简码和城市编码

什么是区域简码? 省市区 首字母 ,例如 河北省 石家庄市 长安区 HBSJZCA

什么是城市编码? 城市全拼 例如: 上海市  shanghai

 

问题: 汉子转换为拼音有什么用?检索!

使用 pinyin4j 工具包 ,完成汉字到拼音的转换

        下载 :http://sourceforge.net/projects/pinyin4j/files/

第一步:  utils模块使用maven坐标 导入pinyin4j

<dependency>

                         <groupId>com.belerweb</groupId>

                         <artifactId>pinyin4j</artifactId>

                 </dependency

第二步: 使用pinyin4j 转换

        在项目导入Pinyin4jUtils 工具类

简码制作

测试工具类:

第三部 web模块导入 utils模块的依赖

Pom.xml

修改RegionAction 一键上传代码

抽取方法封装:

 

// 重定向浏览器发起新的一次请求不可以访问WEB-INF下的资源

        @Action(value = "regionAction_oneclickupload", results = { @Result(name ="oneclickupload", type ="json") })

        public String oneclickupload() {

                 // 解析 excel文档获取数据封装到指定对象 ---->Spring datajpa需要对象决定 region

                 //List<Region>--->spring datajpa

                 // 1: 解析excel Region主键策略修改手动assigned

                 // 2: poi 解析

                 try {

                         // 加载工作簿对象

                         HSSFWorkbookworkbook =new HSSFWorkbook(new FileInputStream(upload));

                         // 获取指定sheet获取第一个sheet

                         HSSFSheetsheet =workbook.getSheetAt(0);

                         List<Region>regions =new ArrayList<Region>();

                         // 读取每一行 = Region

                         for (Rowrow :sheet) {

                                  // 除去第一行获取当前行行号0开始

                                  if (row.getRowNum() == 0) {

                                          continue;

                                  }

                                  Regionregion =new Region();

                                  region.setId(row.getCell(0).getStringCellValue());

                                  region.setProvince(row.getCell(1).getStringCellValue());//江苏

                                  region.setCity(row.getCell(2).getStringCellValue());//南京

                                  region.setDistrict(row.getCell(3).getStringCellValue());//玄武

                                  region.setPostcode(row.getCell(4).getStringCellValue());

                                  // 每一行对象获取添加集合中

                                  Stringshortcode = getShortCode(region.getProvince(),region.getCity(),region.getDistrict());

                                  Stringcitycode = getPinYincode(region.getCity());

                                  region.setShortcode(shortcode);

                                  region.setCitycode(citycode);

                                  regions.add(region);

                         }

                         // 2: 业务层 ...

                         facadeService.getRegionService().save(regions);

                         push(true);

                 }catch (Exceptione) {

                         e.printStackTrace();

                         push(false);

                 }

                 return"oneclickupload";

        }

执行操作

测试 区域批量导入!

如果是直辖市 : 省和市 简码 保留一个即可  封装方法优化

3.  任务三:区域添加

区域添加时,因为id要指定, 页面添加 id 输入框 ,如何保证不重复采用ajax校验!

学员作业:1  区域添加(参照取派员添加 自定义ajax校验)  2:区域修改(参照取派员修改即可)

3:删除取消!

 

4.  任务四:区域分页查询

datagrid 完成 分页查询  region.jsp 页面 datagrid js  url 地址

 

1: 分页查询 region.jsp 页面 编写url 地址

2: 无条件分页查询

编写action

 

3:业务层

Web.xml 解决延迟加载问题配置

配置OpenEnetityManagerInViewFilter 将session生命周期扩大到web层 解决延迟加载问题

回顾: jqueryeasyui datagrid 分页实现过程

1、   编写datagrid 设置url

2、   页面第一次加载后,自动向url发送请求,请求包含 page 页码 和 rows 每页记录数

3、   服务器根据page和rows 封装 Pageable对象 (PageRequest )

4、   调用Spring data  

Page<T>findAll(Pageable ) 返回Page对象

5、   将Page数据转换到符合easyui datagrid 格式对象中 Map

封装 total 总记录数、rows 当前页数据

        6、 将结果转换json返回

 

5.  分页查询结果集优化配置 

后续所有分页查询  ---> 配置全局结果集配置

在不同XxxAction分页查询代码内部结果集统一配置 SUCCESS

以后只要结果集是success--->json 结果集

分析: 分页查询优化封装!

实现代码:

父类BaseAction

 

      // 分页操作接受页面每页显示记录每次easyui发送分页请求父类就可以通过sett方法自动注入页码和每页显示记录数

        packagecn.itcast.mavenbos.action.base;

 

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.HashMap;

import java.util.Map;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

 

importorg.apache.struts2.ServletActionContext;

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.data.domain.Page;

import org.springframework.data.domain.PageRequest;

 

importcn.itcast.mavenbos.service.facade.FacadeService;

 

importcom.opensymphony.xwork2.ActionContext;

importcom.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

import com.opensymphony.xwork2.util.ValueStack;

 

//参数化泛型

@SuppressWarnings("all")

public class BaseAction<T> extendsActionSupport implements ModelDriven<T> {

     protectedT model; // new T();

     //分页操作接受页面每页显示记录

     protectedint page = 1;//页码

     protectedint rows = 10;//每页显示记录数

 

     publicvoid setPage(int page) {

           this.page= page;

     }

 

     publicvoid setRows(int rows) {

           this.rows= rows;

     }

 

     publicT getModel() {

           //TODO Auto-generated method stub

           returnmodel;

     }

 

     //父类抽取封装分页查询数据

     protectedPageRequest getPageRequest() {

           returnnew PageRequest(page - 1, rows);

     }

 

     //父类pageData数据封装Map对象Map存放值栈中

     protectedPage<T> pageData;

 

     //子类调用将数据---->传递给父类分页响应数据对象

     publicvoid setPageData(Page<T> pageData) {

           this.pageData= pageData;

     }

 

     //action中提供getXXX方法 json结果集调用 getXXX 获取值栈数据进行json序列化

     //没有修改栈顶元素

     publicMap<String, Object> getObj() {

           Map<String,Object> pageMapData = new HashMap<String, Object>();

           pageMapData.put("total",pageData.getTotalElements());//总记录数

           pageMapData.put("rows",pageData.getContent());//总记录数

           returnpageMapData;

     }

 

     //父类中注入门面业务层

     @Autowired

     protectedFacadeService facadeService;

 

     //目的获取子类参数化类型

     //父类构造方法中使用参数化泛型+反射获取子类具体泛型对应类型 newInstance 创建实例

     publicBaseAction() {

           //model进行实例化,通过子类类声明的泛型

           Typesuperclass = this.getClass().getGenericSuperclass();

           //转化为参数化类型

           ParameterizedTypeparameterizedType = (ParameterizedType) superclass;

           //获取一个泛型参数

           Class<T>modelClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];

           try{

                model= modelClass.newInstance();

           }catch (InstantiationException e) {

                e.printStackTrace();

           }catch (IllegalAccessException e) {

                e.printStackTrace();

           }

     }

 

     //父类封装通用方法比如值栈操作分页操作 session操作 request操作

     //1: 值栈操作获取值栈

     publicValueStack getValueStack() {

           returnActionContext.getContext().getValueStack();

     }

 

     //压入栈顶

     publicvoid push(Object obj) {

           getValueStack().push(obj);

     }

 

     //压入栈顶map结构<>

     publicvoid set(String key, Object obj) {

           getValueStack().set(key,obj);

     }

 

     //2: session 操作

     publicHttpSession getSession() {

           returnServletActionContext.getRequest().getSession();

     }

 

     publicvoid setSessionAttribute(String key, Object obj) {

           getSession().setAttribute(key,obj);

     }

 

     publicvoid removeSessionAttribute(String key) {

           getSession().removeAttribute(key);

     }

 

     publicObject getSessionAttribute(String key) {

           returngetSession().getAttribute(key);

     }

 

     //3: request

     publicHttpServletRequest getRequest() {

           returnServletActionContext.getRequest();

 

     }

 

     publicString getParameter(String key) {

           returngetRequest().getParameter(key);

     }

 

}      

子类Action 分页代码

struts.xml 结果集配置

封装完成流程说明

 

6.  区域条件查询(扩展)

1: 页面卡片制作原型

 

Region.jsp点击查询 弹窗条件

Js  制作div窗体

Div标签

                 <!--条件查询窗体 -->

                 <divclass="easyui-window" title="区域条件查询"id="searchRegionWindow" closed="true" collapsible="false"minimizable="false" maximizable="false"style="top:20px;left:200px">

                 <divregion="north" style="height:31px;overflow:hidden;"split="false" border="false" >

                         <divclass="datagrid-toolbar">

                                  <aid="search" icon="icon-save" href="#"class="easyui-linkbutton" plain="true" >查询</a>

                         </div>

                 </div>

                

                 <divregion="center" style="overflow:auto;padding:5px;"border="false">

                         <formid="searchRegionForm">

                                  <tableclass="table-edit" width="80%" align="center">

                                          <trclass="title">

                                                  <tdcolspan="2">区域查询信息</td>

                                          </tr>

                                          <tr>

                                                  <td>省</td>

                                                  <td><inputtype="text" name="province"id="sprovince"/></td>

                                          </tr>

                                          <tr>

                                                  <td>市</td>

                                                  <td><inputtype="text" name="city" id="scity"/>

                      </td>

                                          </tr>

                                          <tr>

                                                  <td>区</td>

                                                  <td><inputtype="text" name="district"id="sdistrict"/></td>

                                          </tr>

                                          </table>

                         </form>

                 </div>

        </div>

 

Js进行load条件查询

客户端完成!

 

条件查询Action-àRegionAction重写pageQuery 方法

        @Action(value ="regionAction_pageQuery", results = { @Result(name ="pageQuery", type = "fastJson") })

        public String pageQuery() {

                 // 条件分页查询

                 // 1: 将请求参数封装到 Specification接口实现类中 将接口实现类传递 service

                 Specification<Region>specification = new Specification<Region>() {

                         @Override

                         public PredicatetoPredicate(Root<Region> root, CriteriaQuery<?> query,CriteriaBuilder cb) {

                                  // 根据model接受客户端条件个数 判断specification 封装的具体参数...

                                  // root 指 的是 查询主表对应实体模型 <T> Staff CriteriaBuilder == Restrictions 建立条件对象

                                  List<Predicate>list = new ArrayList<Predicate>();// 集合长度可变 ...

                                  if(StringUtils.isNotBlank(model.getProvince())) {

                                          // 用户在客户端 表单输入 按照名称 模糊查询

                                          list.add(cb.like(root.get("province").as(String.class),"%" + model.getProvince() + "%"));

                                  }

                                  if(StringUtils.isNotBlank(model.getCity())) {

                                          // 用户在客户端 表单输入 按照名称 模糊查询

                                          list.add(cb.like(root.get("city").as(String.class),"%" + model.getCity() + "%"));

                                  }

                                  if(StringUtils.isNotBlank(model.getDistrict())) {

                                          // 用户在客户端 表单输入 按照名称 模糊查询

                                          list.add(cb.like(root.get("district").as(String.class),"%" + model.getDistrict() + "%"));

                                  }

 

                                  Predicate[] p= new Predicate[list.size()];// 要求添加条件数组 (可变参数)

                                  returncb.and(list.toArray(p));// and 所有条件是并且关系 select * from xx where xx= ?1 and xxx= ?2and

                         }

                 };

                 Map<String, Object> map =new HashMap<String, Object>();

                 PageRequest pageRequest = newPageRequest(page - 1, rows);

                 Page<Region> pageDatas =facadeService.getRegionService().pageQuery(specification, pageRequest);

                 // Map = json

                 map.put("total",pageDatas.getTotalElements());

                 map.put("rows",pageDatas.getContent());

                 push(map);

                 return "pageQuery";

        }

 

业务层重写pageQuqyer RegionDao 需要继承 JPaSpecificationExecutor<Region>接口即可

Dao

条件分页查询 完成!

 

 


  

 

0 0
原创粉丝点击