工欲善其事必先利其器,果然有道理,之前經常做一些 Excel 的解析和寫入,大家估計也對 jxl 和 poi 有所耳聞,操作起來那是一塌糊塗,需要了解裡面的各種變量,然而這次我們使用的是阿里開源的 EasyExcel,5分鐘搞定下載和上傳解析。
我們寫代碼之前先說一下我們模擬的場景,我們需要使用 EasyExcel 實現文章的批量上傳和下載。
話不多說直接上代碼,文末可以獲取全部代碼。代碼運行的環境是 Spring Boot,所以具體的 Spring Boot 搭建細節我們就不說了,直接從引入 EasyExcel 開始。
1. 引入依賴<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.4</version>
</dependency>
2. 下載模板如果需要上傳 Excel,勢必需要提前準備好模板,那麼這點 EasyExcel 做的更簡潔,我們直接上代碼。定義一個 download 請求,設置 application/vnd.ms-excel 為了返回內容後直接可以作為 excel 文件下載。下面才是重點。
EasyExcel.write 是設置具體需要映射的對象到返回的流EasyExcel.sheet 設置具體的 sheet 名字EasyExcel.doWrite 寫入具體的內容,也是 write 裡面對應的 Article 對象的列表。EasyExcel
.write(response.getOutputStream(), Article.class)
.sheet("模板")
.doWrite(new ArrayList());@GetMapping("tempalte")
public void tempalte(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("文章模板", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), Article.class).sheet("模板").doWrite(new ArrayList());
}Article.java 類,裡面就比較簡單了,定義了三個屬性,這三個屬性分別通過 ExcelProperty 映射 Excel 的標題,也就是列,一定要有 setter 和 getter 方法,這裡為了依賴少直接生成的,你也可以使用 Lombok。
public class Article {
@ExcelProperty("文章標題")
private String title;
@ExcelProperty("文章連結")
private String link;
@ExcelProperty("閱讀數")
private Integer view;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public Integer getView() {
return view;
}
public void setView(Integer view) {
this.view = view;
}
}接下來我們運行程序EasyExcelApplication(源碼中的啟動類),然後訪問
http://localhost:8080/tempalte神奇的一幕出現了,直接下載下來了一個 excel 文件,內容如下,是不是太簡單了?
上傳根據剛剛下載的模板,把我事先準備好的文章錄入
然後定義一個接口 upload 如下,內容也是非常簡練,使用 EasyExcel.read 方法就可以搞定,其中 file.getInputStream() 是對應的文件輸入流,Article.class 就是剛才我們下載時候定義好的類,因為類型一樣,可以直接復用,ArticleReadListener 就比較重要了,它是用來接收所有解析行。其他的都是固定寫法。
@PostMapping("upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {
EasyExcel.read(file.getInputStream(), Article.class, new ArticleReadListener(articleDao)).sheet().doRead();
return "success";
}ArticleReadListener 需要注意的地方是我不能託管給 Spring 所以需要在構造方法裡面把預先注入的 articleDao 寫進入,articleDao 是為了模擬資料庫操作,為我們稍後的下載提供數據支持。
ArticleReadListener 相對來說也是非常簡單,先實現AnalysisEventListener類並傳入泛型 Article,複寫 invoke 方法解析的每一行 excel,因為傳入了泛型,會自動轉換為 Article,當然它會自動過濾標題行,所以正式解析的就是第一行內容,doAfterAllAnalysed 是讀取完所有內容以後的操作,我們調用 articleDao.save(raws); 把所有解析的內容存入 mock 的資料庫。
public class ArticleReadListener extends AnalysisEventListener<Article> {
private ArticleDao articleDao;
public ArticleReadListener(ArticleDao articleDao) {
this.articleDao = articleDao;
}
private static final Logger logger = LoggerFactory.getLogger(ArticleReadListener.class);
private List<Article> raws = new ArrayList<>();
@Override
public void invoke(Article data, AnalysisContext context) {
logger.info("開始讀取文章:{}", JSON.toJSONString(data));
raws.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
logger.info("一共讀取了{}篇文章,標題分別是:", raws.size(), raws.stream().map(Article::getTitle).collect(Collectors.toList()));
articleDao.save(raws);
}
}ArticleDao 代碼不需要解釋,直接看下
@Service
public class ArticleDao {
private List<Article> articles = new ArrayList<>();
public void save(List<Article> raws) {
articles = raws;
}
public List<Article> list() {
return articles;
}
}然後直接使用 Postman 上傳文件
就可以在控制臺直接看到日誌內容了
開始讀取文章:{"link":"https://mp.weixin.qq.com/s/S0RCVJClS0094kjjmAn8yA","title":"讓人又愛又恨的 Lombok,到底該不該用","view":1378}
開始讀取文章:{"link":"https://mp.weixin.qq.com/s/r6toOIgrt4f9M8j4PGGaFQ","title":"Delombok 是個啥?居然可破 Lombok?","view":1559}
一共讀取了2篇文章,標題分別是:[讓人又愛又恨的 Lombok,到底該不該用, Delombok 是個啥?居然可破 Lombok?]是不是非常簡單就讀取完了?那麼我們繼續完成下載
下載你自己觀察可以看到,下載的代碼和下載模板的代碼基本一樣,唯一的不同.doWrite(articleDao.list()),把之前上傳存入資料庫的內容寫入 excel。
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("文章下載", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel
.write(response.getOutputStream(), Article.class)
.sheet("文章")
.doWrite(articleDao.list());
}話不多說,我們直接訪問 http://localhost:8080/download 看下結果,是不是非常簡單就可以完成上傳和下載?
完整代碼獲取地址
https://github.com/juice-resume/java-programming.git