前面介绍了ssm框架的整合开发以及后端接口部分的实现(如今对这些接口有了新的变动以及优化),本文将整合前端框架jquery-easyui来实现前后端接口的对接,更加直接的展示poi导入导出excel的效果。(视频教程地址:https://edu.csdn.net/course/detail/8894 欢迎支持!!)
对于easyui,除了页面的内容展示以及样式排版外,主要的责任在于请求后端接口拿到数据并填充到相应的页面位置中。其中的接口就包括:获取数据列表,搜索,导出数据,导入数据。
为了展示效果,我结合了企业实际项目中的实际业务模块,就用“产品信息列表”来进行演示。页面起名为product.jsp,并在web.xml将其作为welcome-list的欢迎页面中:
<welcome-file-list>
<!-- <welcome-file>login.jsp</welcome-file> -->
<welcome-file>product.jsp</welcome-file>
</welcome-file-list>
具体的页面代码都在下面了,包括:如果获取数据列表并填充到easyui的datagrid,导出数据到excel,打开对话框上传excel文件导入数据等等:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<c:set var="ctx" value="${pageContext.request.contextPath}" ></c:set>
<link rel="stylesheet" type="text/css" href="${ctx}/jquery-easyui-1.3.3/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="${ctx}/jquery-easyui-1.3.3/themes/icon.css">
<script type="text/javascript" src="${ctx}/jquery-easyui-1.3.3/jquery.min.js"></script>
<script type="text/javascript" src="${ctx}/jquery-easyui-1.3.3/jquery.easyui.min.js"></script>
<script type="text/javascript" src="${ctx}/jquery-easyui-1.3.3/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript">
function searchProduct(){
$("#dg").datagrid('load',{
"name":$("#s_productName").val()
});
}
function exportProduct(){
window.location.href="${ctx}/product/excel/export.do";
}
function openUploadFileDialog(){
$("#dlg2").dialog('open').dialog('setTitle','excel批量导入数据');
}
function uploadExcel(){
$("#uploadForm").form("submit",{
success:function(result){
var result=eval('('+result+')');
if(result.code!=0){
$.messager.alert("系统提示",result.msg);
}else{
$.messager.alert("系统提示","上传成功");
$("#dlg2").dialog("close");
$("#dg").datagrid("reload");
}
}
});
}
</script>
<title>Insert title here</title>
</head>
<body style="margin: 1px">
<%-- <table id="dg" title="产品信息查询" class="easyui-datagrid" fitColumns="true" pagination="true" rownumbers="true"
url="${ctx}/poi/list.do" method="get" fit="true" toolbar="#tb"> --%>
<table id="dg" title="产品信息列表" class="easyui-datagrid" fitColumns="true" pagination="true" rownumbers="true"
fit="true" toolbar="#tb" data-options="singleSelect:true,collapsible:true,url:'${ctx}/product/list.do',method:'get'" >
<thead>
<tr>
<th field="cb" checkbox="true" align="center"></th>
<th data-options="field:'id',width:50">编号</th>
<th data-options="field:'name',width:200">产品名称</th>
<th data-options="field:'unit',width:50">单位</th>
<th data-options="field:'price',width:80">价格</th>
<th data-options="field:'stock',width:80">库存</th>
<th data-options="field:'remark',width:200">备注</th>
<th data-options="field:'purchaseDate',width:100">采购日期</th>
</tr>
</thead>
</table>
<div id="tb">
<div>
产品名称: <input type="text" id="s_productName" size="20" onkeydown="if(event.keyCode==13) searchProduct()"/>
<a href="javascript:searchProduct()" class="easyui-linkbutton" iconCls="icon-search" plain="true">搜索</a>
<a href="javascript:exportProduct()" class="easyui-linkbutton" iconCls="icon-search" plain="true">导出excel</a>
<a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-add" plain="true" onclick="openUploadFileDialog()">导入excel</a>
</div>
</div>
<div id="dlg2" class="easyui-dialog" style="width:400px;height:180px;padding:10px 20px" closed="true" buttons="#dlg-buttons2">
<form id="uploadForm" action="${ctx}/product/excel/upload.do" method="post" enctype="multipart/form-data" >
<table>
<!-- <tr>
<td>下载模版:</td>
<td><a href="javascript:void(0)" class="easyui-linkbutton" onclick="downloadTemplate()">下载模板文件</a></td>
</tr> -->
<tr>
<td>上传文件:</td>
<td><input type="file" name="productFile"></td>
</tr>
</table>
</form>
</div>
<div id="dlg-buttons2">
<a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-ok" onclick="uploadExcel()">上传excel</a>
<a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-cancel" onclick="javascript:$('#dlg2').dialog('close')">关闭</a>
</div>
</body>
</html>
在这里,后端新增了一个ProductController控制器,用于对接上面页面的请求接口,具体代码如下:
package com.debug.steadyjack.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.debug.steadyjack.dto.BaseResponse;
import com.debug.steadyjack.enums.StatusCode;
import com.debug.steadyjack.enums.WorkBookVersion;
import com.debug.steadyjack.mapper.ProductMapper;
import com.debug.steadyjack.model.Product;
import com.debug.steadyjack.service.PoiService;
import com.debug.steadyjack.service.ProductService;
import com.debug.steadyjack.utils.ExcelBeanUtil;
import com.debug.steadyjack.utils.ExcelUtil;
import com.debug.steadyjack.utils.WebUtil;
@Controller
public class ProductController {
private static final Logger log=LoggerFactory.getLogger(ProductController.class);
private static final String prefix="product";
@Value("${poi.excel.sheet.name}")
private String sheetProductName;
@Value("${poi.excel.file.name}")
private String excelProductName;
@Autowired
private ProductMapper productMapper;
@Autowired
private PoiService poiService;
@Autowired
private ProductService productService;
/**
* 获取产品列表
* @param name
* @return
*/
@RequestMapping(value=prefix+"/list",method=RequestMethod.GET)
@ResponseBody
public List<Product> list(String name){
List<Product> products=new ArrayList<Product>();
try {
products=productMapper.selectAll(name);
} catch (Exception e) {
log.error("获取产品列表发生异常: ",e.fillInStackTrace());
}
return products;
}
/**
* 导出excel
* @param response
* @return
*/
@RequestMapping(value=prefix+"/excel/export",method=RequestMethod.GET)
public @ResponseBody String exportExcel(HttpServletResponse response,String search){
try {
List<Product> products=productMapper.selectAll(search);
String[] headers=new String[]{"id编号","名称","单位","单价","库存量","采购日期","备注信息"};
List<Map<Integer, Object>> dataList=ExcelBeanUtil.manageProductList(products);
log.info("excel下载填充数据: {} ",dataList);
Workbook wb=new HSSFWorkbook();
ExcelUtil.fillExcelSheetData(dataList, wb, headers, sheetProductName);
WebUtil.downloadExcel(response, wb, excelProductName);
return excelProductName;
} catch (Exception e) {
log.error("下载excel 发生异常:",e.fillInStackTrace());
}
return null;
}
/**
* 上传excel导入数据
* @param request
* @return
*/
@SuppressWarnings("rawtypes")
@RequestMapping(value=prefix+"/excel/upload",method=RequestMethod.POST,consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public BaseResponse uploadExcel(MultipartHttpServletRequest request){
BaseResponse response=new BaseResponse<>(StatusCode.Success);
try {
MultipartFile file=request.getFile("productFile");
if (file==null || file.getName()==null) {
return new BaseResponse<>(StatusCode.Invalid_Param);
}
String fileName=file.getOriginalFilename();
String suffix=StringUtils.substring(fileName, fileName.lastIndexOf(".")+1);
if (WorkBookVersion.valueOfSuffix(suffix)==null) {
return new BaseResponse<>(StatusCode.WorkBook_Version_Invalid);
}
log.info("文件名:{} 文件后缀名:{} ",fileName,suffix);
Workbook wb=poiService.getWorkbook(file,suffix);
List<Product> products=poiService.readExcelData(wb);
//批量插入-第一种方法
//productService.insertBatch(products);
//批量插入-第二种方法(注意jdbc链接mysql允许批量插入删除的配置)
productMapper.insertBatch(products);
} catch (Exception e) {
log.error("上传excel导入数据 发生异常:",e.fillInStackTrace());
return new BaseResponse<>(StatusCode.System_Error);
}
return response;
}
}
优化过后的PoiService代码如下:
package com.debug.steadyjack.service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.debug.steadyjack.enums.WorkBookVersion;
import com.debug.steadyjack.model.Product;
import com.debug.steadyjack.utils.DateUtil;
import com.debug.steadyjack.utils.ExcelUtil;
@Service
public class PoiService {
private static final Logger log=LoggerFactory.getLogger(PoiService.class);
/**
* 读取excel数据
* @param wb
* @return
* @throws Exception
*/
public List<Product> readExcelData(Workbook wb) throws Exception{
Product product=null;
List<Product> products=new ArrayList<Product>();
Row row=null;
int numSheet=wb.getNumberOfSheets();
if (numSheet>0) {
for(int i=0;i<numSheet;i++){
Sheet sheet=wb.getSheetAt(i);
int numRow=sheet.getLastRowNum();
if (numRow>0) {
for(int j=1;j<=numRow;j++){
//TODO:跳过excel sheet表格头部
row=sheet.getRow(j);
product=new Product();
String name=ExcelUtil.manageCell(row.getCell(1), null);
String unit=ExcelUtil.manageCell(row.getCell(2), null);
Double price=Double.valueOf(ExcelUtil.manageCell(row.getCell(3), null));
String stock=ExcelUtil.manageCell(row.getCell(4), null);
String remark=ExcelUtil.manageCell(row.getCell(6), null);
product.setName(name);
product.setUnit(unit);
product.setPrice(price);
product.setStock(Double.valueOf(stock));
String value=ExcelUtil.manageCell(row.getCell(5), "yyyy-MM-dd");
product.setPurchaseDate(DateUtil.strToDate(value, "yyyy-MM-dd"));
product.setRemark(remark);
products.add(product);
}
}
}
}
log.info("获取数据列表: {} ",products);
return products;
}
/**
* 根据版本来区分获取workbook实例
* @param version
* @return
*/
public Workbook getWorkbook(String version,InputStream inputStream) throws Exception{
Workbook wk=null;
if (Objects.equals(WorkBookVersion.WorkBook2003.getCode(), version)) {
wk=new HSSFWorkbook(inputStream);
}else if (Objects.equals(WorkBookVersion.WorkBook2007.getCode(), version)) {
wk=new XSSFWorkbook(inputStream);
}
return wk;
}
/**
* 根据file区分获取workbook实例
* @param version
* @return
*/
public Workbook getWorkbook(MultipartFile file,String suffix) throws Exception{
Workbook wk=null;
if (Objects.equals(WorkBookVersion.WorkBook2003Xls.getCode(), suffix)) {
wk=new HSSFWorkbook(file.getInputStream());
}else if (Objects.equals(WorkBookVersion.WorkBook2007Xlsx.getCode(), suffix)) {
wk=new XSSFWorkbook(file.getInputStream());
}
return wk;
}
}
以及需要用到根据上传的文件名来决定获取的WorkBook的实例的WorkBookVersion枚举类:
package com.debug.steadyjack.enums;
import java.util.Objects;
public enum WorkBookVersion {
WorkBook2003("2003","2003版本workBook"),
WorkBook2007("2007","2007版本workBook"),
WorkBook2003Xls("xls","xls后缀名结尾-2003版本workBook"),
WorkBook2007Xlsx("xlsx","xlsx后缀名结尾-2007版本workBook");
private String code;
private String name;
private WorkBookVersion(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/*public static WorkBookVersion valueOfVersion(String code){
if (Objects.equals(WorkBook2003.getCode(), code)) {
return WorkBook2003;
}else if (Objects.equals(WorkBook2007.getCode(), code)) {
return WorkBook2007;
}else{
return null;
}
}*/
public static WorkBookVersion valueOfVersion(String version) {
if (Objects.equals(WorkBook2003.getCode(), version)) {
return WorkBook2003;
}else if (Objects.equals(WorkBook2007.getCode(), version)) {
return WorkBook2007;
}else{
return null;
}
}
public static WorkBookVersion valueOfSuffix(String suffix) {
if (Objects.equals(WorkBook2003Xls.getCode(), suffix)) {
return WorkBook2003Xls;
}else if (Objects.equals(WorkBook2007Xlsx.getCode(), suffix)) {
return WorkBook2007Xlsx;
}else{
return null;
}
}
}
到此,就没有了。然后点击项目右键run到tomcat7服务器,可以看到请求了产品的数据列表,搜索,导出数据到Excel以及导入数据到数据并展示在列表中,详细截图如下:
好了,关于springmvc+spring+mybatis整合框架之poi导入导出excel这一系列就介绍到这里来,相关的源码已经贴在这几篇博客了,有相关问题可以加qq咨询:1974544863。
另外,为了能介绍得更加清楚,我将特意将此录制为两三节小视频来介绍这个小项目,包括ssm框架的通用搭建法,整合poi框架实现导入导出excel以及如何整合easyui框架等等,如果需要,可以加上面qq付费领取(毕竟是自己辛勤付出,总要有点回报!),大概35-50块低价出售:包括项目源码、整体框架搭建的全过程以及实战视频、以及售后指导服务!当然啦,如果有需要定制开发的或者有外包的也可以加我上面qq咨询。