前面咱們已經實現了在後臺管理系統中,對配置數據的增刪查改。但每次添加只能添加一條數據,實際生產中,大量數據經過手工一條一條添加不太現實。本章咱們就實現經過Excel導入配置數據的功能。這裏咱們仍是以地圖數據爲例,其餘配置項可參照此例。前端
涉及的功能點主要有對office文檔的編程、文件上傳功能。流程圖大體以下:java
解析office文檔推薦使用免費的開源組件POI,已經能夠知足80%的功能需求。上傳文件須要依賴commons-fileupload包。咱們在pom中添加下列代碼:web
<!-- office組件 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.0</version> </dependency> <!-- 文件上傳 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
另外,以前咱們配置的mvc視圖解析器只能解析簡單的視圖,上傳文件須要支持multipart。在spring-mvc.xml中添加以下配置:spring
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="10485770"></property> <property name="maxInMemorySize" value="10485760"></property> </bean>
這裏配置了上傳最大限制10MB,對於excel上傳來講足矣。數據庫
在MapController中,咱們添加3個方法apache
@ResponseBody @RequestMapping(value = "/importExcel", method = RequestMethod.POST) public Object importExcel(HttpServletRequest request) { try { ServletContext servletContext = request.getServletContext(); String uploadPath = servletContext.getRealPath("/upload"); File dir = new File(uploadPath); if (!dir.exists()) { dir.mkdir(); } CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(servletContext); if (multipartResolver.isMultipart(request)) { MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; Iterator<String> iter = multiRequest.getFileNames(); while (iter.hasNext()) { MultipartFile file = multiRequest.getFile(iter.next()); if (file.getSize() > 0) { String fileName = file.getOriginalFilename(); String extension = fileName.substring(fileName.lastIndexOf(".")); if (!extension.toLowerCase().equals(".xls") && !extension.toLowerCase().equals(".xlsx")) { throw new Exception("不支持的文檔格式!請上傳.xls或.xlsx格式的文檔!"); } String destFileName = fileName + "_" + System.currentTimeMillis() + extension; File destFile = new File(uploadPath, destFileName); file.transferTo(destFile); List<WowMap> dataList = this.loadExcelData(destFile.getPath()); this.saveExcelData(dataList); if (!destFile.delete()) { logger.warn("臨時文件刪除失敗:" + destFile.getAbsolutePath()); } } } } return CommonResult.success(); } catch (Exception ex) { logger.error(ex.getMessage(), ex); return CommonResult.fail(); } } protected List<WowMap> loadExcelData(String excelPath) throws Exception { FileInputStream fileInputStream = new FileInputStream(excelPath); XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); Sheet sheet = workbook.getSheet("地圖"); List<WowMap> wowMapList = new ArrayList<>(); // 處理當前頁,循環讀取每一行 String createUser = this.currentUserName(); for (int rowNum = 2; rowNum <= sheet.getLastRowNum(); rowNum++) { XSSFRow row = (XSSFRow) sheet.getRow(rowNum); String name = PoiUtil.getCellValue(row.getCell(2)); DataDict.Occupy occupy = DataDict.Occupy.getByDesc(PoiUtil.getCellValue(row.getCell(4))); WowMap wowMap = new WowMap(); wowMap.setName(name); wowMap.setOccupy(occupy.getCode()); wowMap.setDescription(""); wowMap.setCreateUser(createUser); wowMapList.add(wowMap); } fileInputStream.close(); return wowMapList; } protected void saveExcelData(List<WowMap> dataList) { wowMapManager.batchInsert(dataList); }
其中,importExcel方法,時候對應前端點擊導入按鈕時的後端入口,在這個方法中,咱們定義了臨時文件上傳路徑,校驗了文件名後綴,保存上傳的文件到服務器,並在操做結束後將臨時文件刪除; loadExcelData方法,利用POI組件讀取解析Excel數據,Excel數據怎麼配咱們能夠自由定義,這裏讀取時自由調整對應的行列便可,本例使用的Excel在文末給出的源碼中能夠找到; saveExcelData方法,將解析到的數據列表存入數據庫,這裏調用的batchInsert批量添加方法,在前面講增刪查改的時候已經提早實現了。編程
另外,在使用POI組件讀取Excel數據時,須要先判斷單元格格式,咱們建立一個工具類PoiUtil來實現此功能,這種在之後的其餘項目中也可使用的工具類,咱們把它提取出來,放到util模塊中,做爲咱們的通用工具包,以便往後使用。在util模塊新建包com.idlewow.util.poi,並添加PoiUtil類:後端
package com.idlewow.util.poi; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.DateUtil; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; public class PoiUtil { public static String getCellValue(Cell cell) { CellType cellType = cell.getCellType(); if (cellType.equals(CellType.STRING)) { return cell.getStringCellValue(); } else if (cellType.equals(CellType.NUMERIC)) { if (DateUtil.isCellDateFormatted(cell)) { Date date = cell.getDateCellValue(); return date == null ? "" : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); } else { return new DecimalFormat("0.##").format(cell.getNumericCellValue()); } } else if (cellType.equals(CellType.FORMULA)) { if (StringUtils.isNotBlank(cell.getStringCellValue())) { return cell.getStringCellValue(); } else { return cell.getNumericCellValue() + ""; } } else if (cellType.equals(CellType.BOOLEAN)) { return cell.getBooleanCellValue() ? "TRUE" : "FALSE"; } else { return ""; } } }
工具類提取到util模塊後,須要在util模塊也添加對Poi的依賴,並在rms模塊添加對util的依賴。這裏util模塊中,依賴項的scope爲provided便可,僅在編譯階段使用,由於在引用此工具包的模塊中確定已經引入了POI依賴,無需重複打包:spring-mvc
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.0</version> <scope>provided</scope> </dependency> </dependencies>
在地圖列表頁面list.jsp中,添加導入excel的按鈕。服務器
<form> ………… ………… <div class="layui-inline layui-show-xs-block"> <button type="button" class="layui-btn" onclick="xadmin.open('添加地圖','add',500,500)"> <i class="layui-icon"></i>添加地圖 </button> </div> <div class="layui-upload layui-inline layui-show-xs-block"> <button type="button" class="layui-btn layui-btn-normal" id="btnSelectFile">選擇Excel</button> <button type="button" class="layui-btn" id="btnImport">開始導入</button> </div> </form>
在列表頁面的list.js中,綁定相應的按鈕事件。
layui.use(['upload', 'table', 'form'], function () { ………… ………… layui.upload.render({ elem: '#btnSelectFile', url: '/manage/map/importExcel', accept: 'file', exts: 'xls|xlsx', auto: false, bindAction: '#btnImport', done: function (result) { if (result.code === 1) { layer.alert(result.message, {icon: 6}, function () { layui.layer.closeAll(); layui.table.reload('datatable'); }); } else { layer.alert(result.message, {icon: 5}); } } }); });
以上,excel導入的功能就所有完成了,咱們運行下看下效果:
本章經過導入Excel文件,實現了批量錄入的功能。
源碼下載地址:https://idlestudio.ctfile.com/fs/14960372-383760599
下一章,預計實現添加、修改時的參數校驗。
歡迎催更!