1. 程式人生 > >SpringMvc實現匯出Excel檢視

SpringMvc實現匯出Excel檢視

   SpringMvc提供了AbstractXlsView提供Excel檢視,它是一個抽象類,提供了一個抽象方法-buildExcelDocument要去實現,其它方法,AbstractXlsView其它方法已經實現了

    buildExcelDocuent主要任務是去建立一個workbook,它要用到POI的API

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

然後我們開始實現這個檢視,這個檢視不是一個邏輯檢視,所以無需檢視解析器也可以實現它,程式碼如下

package com.example.eurekaclient.excel;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.servlet.view.document.AbstractXlsView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @ClassName ExcelView
 * @Description TODO
 * @Author Mr.G
 * @Date 2018/9/20 18:19
 * @Version 1.0
 */
public class ExcelView extends AbstractXlsView {
    private String fileName=null;
    private ExcelExportService excelExportService=null;
    public ExcelView(ExcelExportService excelExportService){
        this.excelExportService=excelExportService;
    }
    public ExcelView(String fileName,ExcelExportService excelExportService){
        this.fileName=fileName;
        this.excelExportService=excelExportService;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public ExcelExportService getExcelExportService() {
        return excelExportService;
    }

    public void setExcelExportService(ExcelExportService excelExportService) {
        this.excelExportService = excelExportService;
    }

    /**
     * Application-provided subclasses must implement this method to populate
     * the Excel workbook document, given the model.
     *
     * @param model    the model Map
     * @param workbook the Excel workbook to populate
     * @param request  in case we need locale etc. Shouldn't look at attributes.
     * @param response in case we need to set cookies. Shouldn't write to it.
     */
    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
       if(excelExportService==null){
           throw new RuntimeException("匯出介面不能為空");
       }
       if(!StringUtils.isEmpty(fileName)){
           String reqCharset=request.getCharacterEncoding();
           reqCharset=reqCharset==null?"UTF-8":reqCharset;
           fileName=new String(fileName.getBytes(reqCharset),"ISO8859-1");
           response.setHeader("Content-disposition","attachment;fileName="+fileName);
       }
       excelExportService.makeWorkBook(model,workbook);

    }
}

fileName是下載檔案的名字,excelExportService是建立Workbook的規則,因為我們會根據不同需求建立不同形式的excel表格,所以我們把這個介面抽象出來當作公用介面,有不同需求的話,就用不同的方式去實現

寫出這個介面

package com.example.eurekaclient.excel;

import org.apache.poi.ss.usermodel.Workbook;

import java.util.Map;

/**
 * @ClassName ExcelExportService
 * @Description TODO
 * @Author Mr.G
 * @Date 2018/9/11 22:23
 * @Version 1.0
 */
public interface ExcelExportService {

    public void makeWorkBook(Map<String,Object> model, Workbook workbook);
}

然後去寫這個介面的實現

package com.example.eurekaclient.excel;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import com.example.eurekaclient.swagger2.entity.User;
import com.example.eurekaclient.swagger2.server.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;
import java.util.Map;

/**
 * @ClassName ExcelController
 * @Description TODO
 * @Author Mr.G
 * @Date 2018/9/21 10:16
 * @Version 1.0
 */
@RestController
@RequestMapping("excel")
public class ExcelController {
    @Autowired
    private UserService userService;
    @RequestMapping(value="export",method=RequestMethod.GET)
    public ModelAndView export(){
        ModelAndView mv=new ModelAndView();
        ExcelView ev=new ExcelView(exportService());
        ev.setFileName("所有角色.xlsx");
        List<User> userList =userService.selectAll();
        mv.addObject("userList",userList);
        mv.setView(ev);
        return mv;
    }
    @SuppressWarnings({ "unchecked"})
    private ExcelExportService exportService(){
        return (Map<String,Object> model,Workbook workbook)->{
            List<User> userList=(List<User>)model.get("userList");
            Sheet sheet=workbook.createSheet("所有角色");
            Row title= sheet.createRow(0);
            title.createCell(0).setCellValue("姓名");
            title.createCell(1).setCellValue("年紀");
            for(int i=0;i<userList.size();i++){
              User user=userList.get(i);
              Row row=sheet.createRow(i+1);
              row.createCell(0).setCellValue(user.getName());
              row.createCell(1).setCellValue(user.getAge());

            }
        };
    }
}

我們這裡用了lambda表示式,去實現Workbook格式的介面,檔名是所有角色,表格有兩列,用的是springCloud系列的資料庫

user表

這裡講解一個我當時困惑後來想明白的點,我們的Excel檢視是繼承AbstactXlsView,而AbstactXlsView繼承ModelAndView,所以當我們返回mv時,它會通過呼叫渲染的方法,而AbstactXlsView是實現了自己的渲染方法,我們規則都給了它,它會根據這些規則渲染我們需要的表格

程式碼結束了,上效果圖