哈喽,大家好!我是话里人,欢迎大家来到本期Blog,本期将对EasyExcel和POI作为前置知识快速入门,为项目的继续运行做好铺垫~

目录

  • 在线教育
  • 1. EasyExcel 入门
    • 1.1 EasyExcel概述
    • 1.2 EasyExcel 特点
    • 1.3 环境搭建
      • 1.3.1 测试父项目
      • 1.3.2 测试excel项目
    • 1.4 基本操作
      • 1.4.1 测试JavaBean
      • 1.4.2 测试文件路径
      • 1.4.3 写操作
      • 1.4.3 读操作
    • 1.5 复杂操作
      • 1.5.1 复合表头
      • 1.5.2 写操作:多表
      • 1.5.3 读操作:多表
      • 1.6.4 写操作:多对象
    • 1.6 扩展:excel备份数据库
  • 2. 课程科目操作
    • 2.0 分析
    • 2.1 环境搭建
      • 2.1.1 数据库
      • 2.1.2 后端:环境
      • 2.1.3 后端:基本模块
      • 2.1.4 前端
    • 2.2 查询所有
      • 2.2.1 后端实现
      • 2.2.2 前端接口
      • 2.2.3 前端实现
    • 2.3 导入科目
      • 2.3.1 需求
      • 2.3.2 前端
      • 2.3.2 前端:完整版
      • 2.3.4 后端
        • 1) 完善JavaBean
        • 2)填充数据处理类
        • 3)service:通过title查询
        • 4)controller:上传
        • 5)excel内容封装类
        • 6)上传内容处理类
  • 3.POI入门
    • 3.1 POI 概述
      • 3.1.1 简介
      • 3.1.2 官网
    • 3.2 入门案例
      • 3.2.1 环境搭建
      • 3.2.2 xls文件写操作
      • 3.2.3 xlsx 文件写操作
      • 3.2.4 xls 文件读操作
      • 3.2.5 xlsx 文件读操作
      • 3.2.6 读取不同类型的数据
  • end

在线教育

1. EasyExcel 入门

1.1 EasyExcel概述

​ EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel工具。

​ 官网: https://easyexcel.opensource.alibaba.com/docs/current/

​ Github地址:https://github.com/alibaba/easyexcel

1.2 EasyExcel 特点

  • Java解析、生成Excel比较有名的框架有Apache poi、jxl,但他们都存在一个严重的问题就是非常的耗内存。

  • EasyExcel 重写了poi,使一个3M的excel只需要几M内存,并且再大的excel不会出现内存溢出。

    • 64M内存1分钟内读取75M(46W行25列)的Excel。

1.3 环境搭建

1.3.1 测试父项目

  • 项目名:zx-test-parent

  • 修改pom文件

        <dependencies><!-- 测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies>
    

1.3.2 测试excel项目

  • 项目名:zx-test-excel

  • 修改pom,添加依赖

        <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
    

1.4 基本操作

1.4.1 测试JavaBean

package com.czxy.zx.demo01;import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;import java.util.Date;/*** Created by tanxintong.*/
@Data
public class Student {@ExcelProperty("编号")private String id;@ExcelProperty("姓名")private String name;@ExcelProperty("年龄")private Integer age;@ExcelProperty("电话")private String telephone;@ExcelProperty("邮箱")private String email;@ExcelProperty("生日")private Date brithday;
}

1.4.2 测试文件路径

package com.czxy.zx.demo01;import org.junit.jupiter.api.Test;/*** @author txt* @email tanxintong9968@163.com*/
public class TestExcel {/*** 获得根路径* @return*/public String getPath() {return this.getClass().getResource("/").getPath();}@Testpublic void testPath() {// 测试文件路径String path = getPath() + "student_demo.xls";System.out.println(path);}}

1.4.3 写操作

  • excel 属于 office组件一个软件

  • 存在若干版本,大体上划分2种情况,2007前的,2007年后的

    • 2003版:扩展名 xls,内容比较少,最大单元格 IV65536 ,256列(IV)
    • 2007版:扩展名 xlsx,内容较多,最大单元格 XFD1048576,16384列(XFD)
   /*** 准备数据* @return*/private List<Student> getData(){List<Student> list = new ArrayList<Student>();for(int i = 0 ; i < 10 ; i ++){Student student = new Student();student.setId("stu" + i);student.setName("wang" + i);student.setAge( 18 + i );student.setTelephone("1361234" + i);student.setEmail("wang" + i + "@czxy.com");student.setBrithday(new Date());list.add(student);}return list;}@Testpublic void testWrite(){String file = getPath() + "student_demo.xls";//EasyExcel.write(位置,对象).sheet("表名").doWrite(数据);EasyExcel.write(file,Student.class).sheet("班级").doWrite(getData());}

1.4.3 读操作

  • 处理类:

    • 处理类需要实现 AnalysisEventListener 接口
    package com.czxy.zx.demo01;import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.czxy.zx.domain.Student;/*** @author txt* @email tanxintong9968@163.com*/
    public class StudentListener extends AnalysisEventListener<Student> {@Overridepublic void invoke(Student student, AnalysisContext analysisContext) {System.out.println(student);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {System.out.println("解析完成");}
    }
  • 测试

        @Testpublic void testRead(){String file = getPath() + "student_demo.xls";//EasyExcel.read(文件, 封装对象, 处理类).sheet("表").doRead();EasyExcel.read(file, Student.class, new StudentListener()).sheet("班级").doRead();}
    

1.5 复杂操作

1.5.1 复合表头

package com.czxy.zx.demo02;import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.format.DateTimeFormat;import com.alibaba.excel.annotation.write.style.ColumnWidth;import com.alibaba.excel.annotation.write.style.ContentRowHeight;import com.alibaba.excel.annotation.write.style.HeadRowHeight;import lombok.Data;import java.util.Date;/*** @author txt* @email tanxintong9968@163.com*/
@Data
@ContentRowHeight(20)
@HeadRowHeight(20)  //行高
@ColumnWidth(25)    //列宽
public class Student2 {@ExcelProperty("编号")private String id;@ExcelProperty({"基本信息","姓名"})   //复制表头private String name;@ExcelProperty({"基本信息","年龄"})private Integer age;@ExcelProperty("电话")private String telephone;@ExcelProperty("邮箱")private String email;@ExcelProperty("生日")@DateTimeFormat("yyyy年MM月dd日")private Date brithday;
}

1.5.2 写操作:多表

package com.czxy.zx.demo02;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.czxy.zx.demo01.Student;
import org.junit.Test;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @author txt* @email tanxintong9968@163.com*/
public class TestExcel2 {/*** 获得根路径* @return*/public String getPath() {return this.getClass().getResource("/").getPath();}/*** 准备数据* @return*/private List<Student2> getData(Integer flag){List<Student2> list = new ArrayList<Student2>();for(int m = 0 ; m < 10 ; m ++){String i = "" + flag + m ;Student2 student = new Student2();student.setId("stu" + i);student.setName("wang" + i);student.setAge( 18 );student.setTelephone("1361234" + i);student.setEmail("wang" + i + "@czxy.com");student.setBrithday(new Date());list.add(student);}return list;}@Testpublic void testMoreSheetWrite(){String file = getPath() + "student_demo2.xls";ExcelWriter excelWriter = EasyExcel.write(file).build();for (int i = 0; i < 5; i++) {WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(Student2.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<Student2> data = getData(i);excelWriter.write(data, writeSheet);}excelWriter.finish();}}

1.5.3 读操作:多表

  • 具有缓存处理类

    package com.czxy.zx.demo02;import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;import java.util.ArrayList;
    import java.util.List;/*** Created by tanxintong.*/
    public class Student2Listener extends AnalysisEventListener<Student2> {// 批量操作数private static final int BATCH_COUNT = 10;// 用于缓存信息private List<Student2> cache = new ArrayList<Student2>();public void invoke(Student2 student, AnalysisContext analysisContext) {//保存学生信息cache.add(student);if(cache.size() >= BATCH_COUNT){// 保存数据saveData();}}public void doAfterAllAnalysed(AnalysisContext analysisContext) {//最后的不够 BATCH_COUNT 倍数saveData();}private void saveData() {// 集合不为空if(! cache.isEmpty()) {// 处理缓存数据System.out.println(cache);// 清空缓存cache.clear();}}
    }
  • 读操作

    @Testpublic void testMoreRead(){String file = getPath() + "student_demo2.xls";//EasyExcel.read(文件, 封装对象, 处理类).sheet("表").doRead();ExcelReader excelReader = EasyExcel.read(file, Student2.class, new Student2Listener()).build();// 确定需要解析的sheetfor (int i = 0; i < 5; i++) {ReadSheet readSheet = EasyExcel.readSheet("模板" + i).build();excelReader.read(readSheet);}excelReader.finish();}
    

1.6.4 写操作:多对象

  • Student

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {@ExcelProperty("姓名")private String name;@ExcelProperty("年龄")private Integer age;
    }
  • Book

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @HeadRowHeight(50)
    @HeadFontStyle(fontName = "黑体",italic =  BooleanEnum.TRUE, color = Font.COLOR_RED, underline = 2)
    public class Book {@ExcelProperty("编号")private String id;@ExcelProperty({"作者信息","姓名"})private String authorName;@ExcelProperty({"作者信息","年龄"})private Integer authorAge;@ExcelProperty({"书籍基本信息","标题"})private String title;@ContentFontStyle(fontName = "楷书",italic =  BooleanEnum.TRUE, color = Font.COLOR_RED, underline = -1)@ExcelProperty({"书籍基本信息","价格"})private Double price;@ExcelProperty({"书籍基本信息","出版日期"})@DateTimeFormat("yyyy年MM月dd日")private Date publishDate;
    }
    
  • 实现

    package com.czxy.zx.demo03;import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.ExcelWriter;
    import com.alibaba.excel.write.metadata.WriteSheet;
    import com.czxy.zx.demo01.Student;
    import com.czxy.zx.demo02.Book;
    import org.junit.Test;import java.util.*;/*** @author txt* @email tanxintong9968@163.com*/
    public class TestManyObject {// 获得当前项目的运行时的根目录public String getPath() {return this.getClass().getResource("/").getPath();}// 模拟数据public List<Student> getStudentData() {List<Student> list = new ArrayList<>();for (int i = 0; i < 20; i++) {list.add(new Student("张三" + i, 18 + i));}return list;}public List<Book> getBookData() {List<Book> list = new ArrayList<>();for (int i = 0; i < 20; i++) {list.add(new Book(i+"" , "张三" + i , 18 +i, "坏蛋是怎么"+i, 998d+i, new Date()));}return list;}// 遍历map即可private Map<Class<?>, List<?>> getData() {Map<Class<?>, List<?>> map = new HashMap<>();map.put(Student.class, getStudentData());map.put(Book.class, getBookData());return map;}@Testpublic void testManyObject() {String file = getPath() + "many_object.xlsx";//1 开始写ExcelWriter excelWriter = EasyExcel.write(file).build();//2 依次写每一个对象for(Map.Entry<Class<?>, List<?>> entry : getData().entrySet()) {Class<?> clazz = entry.getKey();            //类型List<?> data = entry.getValue();            //数据WriteSheet writeSheet = EasyExcel.writerSheet(clazz.getSimpleName()).head(clazz).build();excelWriter.write(data, writeSheet);}//3 写完成excelWriter.finish();}
    }

1.6 扩展:excel备份数据库

  • 步骤

    • 步骤1:添加坐标
    • 步骤2:编写封装类
    • 步骤3:编写核心类

  • 步骤1:添加坐标

        <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.7</version></dependency></dependencies>
    
  • 步骤2:编写封装类

    package com.czxy.zx.demo03;import com.alibaba.excel.annotation.ExcelProperty;
    import com.alibaba.excel.annotation.write.style.ColumnWidth;
    import com.alibaba.excel.annotation.write.style.ContentRowHeight;
    import com.alibaba.excel.annotation.write.style.HeadRowHeight;
    import lombok.Data;import java.util.Date;
    import java.util.List;/*** 课程**/
    @Data
    @ContentRowHeight(20)
    @HeadRowHeight(20)  //行高
    @ColumnWidth(25)    //列宽
    public class Chapter {@ExcelProperty("章节ID")private String id;@ExcelProperty("课程ID")private String courseId;@ExcelProperty("章节名称")private String title;@ExcelProperty("显示排序")private Integer sort;@ExcelProperty("创建时间")private Date gmtCreate;@ExcelProperty("更新时间")private Date gmtModified;}
    package com.czxy.zx.demo03;import com.alibaba.excel.annotation.ExcelProperty;
    import com.alibaba.excel.annotation.format.DateTimeFormat;
    import com.alibaba.excel.annotation.write.style.ColumnWidth;
    import com.alibaba.excel.annotation.write.style.ContentRowHeight;
    import com.alibaba.excel.annotation.write.style.HeadRowHeight;
    import lombok.Data;import java.util.Date;/*** 课程**/
    @Data
    @ContentRowHeight(20)
    @HeadRowHeight(20)  //行高
    @ColumnWidth(25)    //列宽
    public class Course {@ExcelProperty("课程ID")private String id;@ExcelProperty("课程讲师ID")private String teacherId;@ExcelProperty("课程专业ID二级分类ID")private String subjectId;@ExcelProperty("一级分类ID")private String subjectParentId;@ExcelProperty("课程标题")private String title;@ExcelProperty("课程销售价格,设置为0则可免费观看")private Double price;@ExcelProperty("总课时")private Integer lessonNum;@ExcelProperty("课程封面图片路径")private String cover;@ExcelProperty("销售数量")private Long buyCount;@ExcelProperty("浏览数量")private Long viewCount;@ExcelProperty("乐观锁")private Long version;@ExcelProperty("视频状态 Draft未发布  Normal已发布")private String status;@ExcelProperty("创建时间")@DateTimeFormat("yyyy年MM月dd日")private Date gmtCreate;@ExcelProperty("更新时间")@DateTimeFormat("yyyy年MM月dd日")private Date gmtModified;}
  • 步骤3:编写核心类

    package com.czxy.zx.demo03;import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.ExcelWriter;
    import com.alibaba.excel.write.metadata.WriteSheet;
    import com.czxy.zx.demo02.Student2;
    import org.apache.commons.dbutils.BasicRowProcessor;
    import org.apache.commons.dbutils.DbUtils;
    import org.apache.commons.dbutils.GenerousBeanProcessor;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.junit.Test;import java.sql.*;
    import java.util.*;/*** @author txt* @email tanxintong9968@163.com*/
    public class TestBackdb {public Class getClassByTableName(String tableName) {Map<String,Class> map = new HashMap<>();map.put("edu_chapter", Chapter.class);map.put("edu_course", Course.class);return map.get(tableName);}public String getPath() {return this.getClass().getResource("/").getPath();}public Connection getConnection() {try {Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://127.0.0.1:3306/zx_edu_course?useUnicode=true&characterEncoding=utf8";String username = "root";String password = "1234";Properties props =new Properties();props.setProperty("user", username);props.setProperty("password", password);props.setProperty("remarks", "true");               //设置可以获取remarks信息props.setProperty("useInformationSchema", "true");  //设置可以获取tables remarks信息return DriverManager.getConnection(url, props);} catch (Exception e) {throw new RuntimeException(e);}}@Testpublic void testDB() throws Exception {String file = getPath() + "db.xls";QueryRunner queryRunner = new QueryRunner();ExcelWriter excelWriter = EasyExcel.write(file).build();String dbName = "zx_edu_course";//获得连接Connection conn = getConnection();//语句执行者Statement st = conn.createStatement();//数据库的元数据DatabaseMetaData databaseMetaData = conn.getMetaData();//获得所有的数据库ResultSet catalogResultSet = databaseMetaData.getCatalogs();//遍历所有的数据库while(catalogResultSet.next()) {//获得数据库的名称String databaseName = catalogResultSet.getString(1);if(dbName.equals(databaseName)) {//使用数据库st.execute("use " + databaseName);ResultSet tableResultSet = databaseMetaData.getTables(databaseName, null, null, null);//遍历所有的表名while(tableResultSet.next()) {//表名String tableName = tableResultSet.getString(3);             //TABLE_NAMEString tableRemarks = tableResultSet.getString("REMARKS"); //获得表的备注// 通过表名获得excel处理类Class excelBeanClass = getClassByTableName(tableName);if(excelBeanClass != null) {//获得当前表的所有数据String sql = "select * from " + tableName;//List data = (List) queryRunner.query(conn, sql, new BeanListHandler<>(excelBeanClass, new BasicRowProcessor(new GenerousBeanProcessor()) ));// 创建sheetWriteSheet writeSheet = EasyExcel.writerSheet(tableRemarks != null ? tableRemarks : tableName).head(excelBeanClass).build();excelWriter.write(data, writeSheet);}}}}//写入完成excelWriter.finish();}}

2. 课程科目操作

2.0 分析

2.1 环境搭建

2.1.1 数据库

CREATE DATABASE zx_edu_course;
USE zx_edu_course;CREATE TABLE `edu_subject`  (`id` VARCHAR(32) NOT NULL PRIMARY KEY COMMENT '课程科目ID',`title` VARCHAR(10) NOT NULL COMMENT '科目名称',`parent_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '父ID',`sort` INT(10)  NOT NULL DEFAULT 0 COMMENT '排序字段',`gmt_create` DATETIME NOT NULL COMMENT '创建时间',`gmt_modified` DATETIME NOT NULL COMMENT '更新时间'
) COMMENT = '课程科目';INSERT INTO `edu_subject` VALUES ('1', '云计算', '0', 0, '2020-06-26 09:41:21', '2020-02-20 23:25:58');
INSERT INTO `edu_subject` VALUES ('2', '系统/运维', '0', 0, '2020-02-20 23:29:59', '2020-02-20 23:29:59');
INSERT INTO `edu_subject` VALUES ('3', '数据库', '0', 0, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('4', '服务器', '0', 0, '2020-02-20 23:30:19', '2020-02-20 23:30:19');INSERT INTO `edu_subject` VALUES ('5', 'MySQL', '3', 1, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('6', 'Oracle', '3', 2, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('7', 'Tomcat', '4', 1, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('8', 'Nginx ', '4', 2, '2020-02-20 23:30:13', '2020-02-20 23:30:13');INSERT INTO `edu_subject` VALUES ('9', 'MySQL优化', '5', 1, '2020-02-20 23:30:13', '2020-02-20 23:30:13');

2.1.2 后端:环境

  • 项目名:zx-service-course

  • pom文件

    <dependencies><!--web起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos 客户端 --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId></dependency><!-- nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency><!-- feign 远程调用 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- mybatis plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis.plus.version}</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--自定义项目--><dependency><groupId>com.czxy.zx</groupId><artifactId>zx-common31</artifactId></dependency><dependency><groupId>com.czxy.zx</groupId><artifactId>zx-domain31</artifactId></dependency><!-- redis 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- JavaMail 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><!-- MQ 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><!--开发者工具--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version></dependency></dependencies>
    
  • yml文件

    # 服务端口号
    server:port: 9020
    # 服务名
    spring:application:name: course-servicedatasource:driverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/zx_edu_course?useUnicode=true&characterEncoding=utf8username: rootpassword: 1234druid:    #druid 连接池配置initial-size: 1       #初始化连接池大小min-idle: 1           #最小连接数max-active: 20        #最大连接数test-on-borrow: true  #获取连接时候验证,会影响性能cloud:nacos:discovery:server-addr: 127.0.0.1:8848   #nacos服务地址redis:database: 0       #数据库索引,取值0-15,表示16个库可选择host: 127.0.0.1   #服务器地址port: 6379        #服务器连接端口号mail:host: smtp.126.com          #发送邮件服务器username: itcast_lt@126.com #账号password: 1qaz2wsx          #密码default-encoding: UTF-8     #默认编码时rabbitmq:host: 127.0.0.1port: 5672username: guestpassowrd: guestvirtualHost: /devtools:restart:enabled: true  #设置开启热部署additional-paths: src/main/java #重启目录exclude: WEB-INF/**freemarker:cache: false    #页面不加载缓存,修改即时生效#开启log4j打印SQL语句
    logging:level:com:czxy:mapper: debug# mp日志打印
    mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 启动类

    package com.czxy.zx;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;/*** @author txt* @email tanxintong9968@163.com*/
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class CourseServiceApplication {public static void main(String[] args) {SpringApplication.run(CourseServiceApplication.class,args);}
    }
  • 拷贝配置

  • 配置类 – MyBatisPlusConfig

package com.czxy.zx.course.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}
}
  • 配置类 – Swagger2ConfigurationV3
package com.czxy.zx.course.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;
import java.util.List;/*** Swagger2 配置类,* 访问路径:swagger-ui.html* 自动注册:*     位置:resources/META-INF/spring.factories*     内容:*        org.springframework.boot.autoconfigure.EnableAutoConfiguration=\*          com.czxy.changgou4.config.Swagger2Configuration*/
@Configuration
@EnableSwagger2
public class Swagger2ConfigurationV3 {@Beanpublic Docket createRestApi() {// 1 确定文档Swagger版本Docket docket = new Docket(DocumentationType.SWAGGER_2);// 2 设置 api基本信息docket.apiInfo(apiInfo());// 3 设置自定义加载路径docket = docket.select().apis(RequestHandlerSelectors.basePackage("com.czxy")).paths(PathSelectors.any()).build();//4 设置权限docket.securitySchemes(securitySchemes());docket.securityContexts(securityContexts());return docket;}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("API").description("基于swagger接口文档").contact(new Contact("梁桐","http://www.javaliang.com","liangtong@itcast.cn")).version("1.0").build();}private List<ApiKey> securitySchemes() {List<ApiKey> list = new ArrayList<>();// name 为参数名  keyname是页面传值显示的 keyname, name在swagger鉴权中使用list.add(new ApiKey("Authorization", "X-Token", "header"));return list;}private List<SecurityContext> securityContexts() {List<SecurityContext> list = new ArrayList<>();list.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("^(?!auth).*$")).build());return list;}private List<SecurityReference> defaultAuth() {AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;List<SecurityReference> list = new ArrayList();list.add(new SecurityReference("Authorization", authorizationScopes));return list;}}

2.1.3 后端:基本模块

  • 创建JavaBean

    package com.czxy.zx.domain;import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import lombok.Data;
    import org.springframework.format.annotation.DateTimeFormat;import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;/*** 课程科目(EduSubject)表实体类** @author txt*/
    @Data
    @TableName("edu_subject")
    public class EduSubject{@TableId(type = IdType.ASSIGN_UUID)//课程科目IDprivate String id;//科目名称private String title;//父IDprivate String parentId;//排序字段private Integer sort;//创建时间@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date gmtCreate;//更新时间@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date gmtModified;@TableField(exist = false)@JsonInclude(JsonInclude.Include.NON_EMPTY)     //生成json数据,不包含空元素private List<EduSubject> children = new ArrayList<>();}
    
  • 创建mapper

package com.czxy.zx.course.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.zx.domain.EduSubject;
import org.apache.ibatis.annotations.Mapper;/*** @author txt* @email tanxintong9968@163.com*/
@Mapper
public interface EduSubjectMapper extends BaseMapper<EduSubject> {}
  • 创建service

    • 接口

      package com.czxy.zx.course.service;import com.baomidou.mybatisplus.extension.service.IService;
      import com.czxy.zx.domain.EduSubject;/*** @author txt* @email tanxintong9968@163.com*/
      public interface EduSubjectService extends IService<EduSubject> {}
    • 实现类

      package com.czxy.zx.course.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import com.czxy.zx.course.mapper.EduSubjectMapper;
      import com.czxy.zx.course.service.EduSubjectService;
      import com.czxy.zx.domain.EduSubject;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;/*** @author txt* @email tanxintong9968@163.com*/
      @Service
      @Transactional
      public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {}
  • 创建controller

    package com.czxy.zx.course.controller;import com.czxy.zx.course.service.EduSubjectService;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @author txt* @email tanxintong9968@163.com*/
    @RestController
    @RequestMapping("/subject")
    public class EduSubjectController {@Resourceprivate EduSubjectService eduSubjectService;}
  • 配置类

  • 配置类 – MyBatisPlusConfig

package com.czxy.zx.course.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}
}
  • 配置类 – Swagger2ConfigurationV3
package com.czxy.zx.course.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;
import java.util.List;/*** Swagger2 配置类,* 访问路径:swagger-ui.html* 自动注册:*     位置:resources/META-INF/spring.factories*     内容:*        org.springframework.boot.autoconfigure.EnableAutoConfiguration=\*          com.czxy.changgou4.config.Swagger2Configuration*/
@Configuration
@EnableSwagger2
public class Swagger2ConfigurationV3 {@Beanpublic Docket createRestApi() {// 1 确定文档Swagger版本Docket docket = new Docket(DocumentationType.SWAGGER_2);// 2 设置 api基本信息docket.apiInfo(apiInfo());// 3 设置自定义加载路径docket = docket.select().apis(RequestHandlerSelectors.basePackage("com.czxy")).paths(PathSelectors.any()).build();//4 设置权限docket.securitySchemes(securitySchemes());docket.securityContexts(securityContexts());return docket;}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("API").description("基于swagger接口文档").contact(new Contact("梁桐","http://www.javaliang.com","liangtong@itcast.cn")).version("1.0").build();}private List<ApiKey> securitySchemes() {List<ApiKey> list = new ArrayList<>();// name 为参数名  keyname是页面传值显示的 keyname, name在swagger鉴权中使用list.add(new ApiKey("Authorization", "X-Token", "header"));return list;}private List<SecurityContext> securityContexts() {List<SecurityContext> list = new ArrayList<>();list.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("^(?!auth).*$")).build());return list;}private List<SecurityReference> defaultAuth() {AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;List<SecurityReference> list = new ArrayList();list.add(new SecurityReference("Authorization", authorizationScopes));return list;}}

2.1.4 前端

  • 创建路由模块

    /** When your routing table is too long, you can split it into small modules **/import Layout from '@/layout'const courseRouter = {path: '/course',           // 当前模块前缀路径,必须以/开头component: Layout,          // 采用布局组件显示当前模块【默认】redirect: '/course/subjectList',  // “教师管理”默认显示路由name: '课程管理',            // 路由名称meta: {title: '课程管理',         // 一级菜单名称,children.length==0 隐藏icon: 'table'             // 一级菜单图标,children.length==0 隐藏},children: [{path: 'subjectList',component: () => import('@/views/edu/course/subjectList.vue'),name: '科目列表',meta: { title: '科目列表', icon: 'list' }   //二级菜单名称}]
    }
    export default courseRouter
  • 创建 subjectList.vue 页面

  • 配置路由

2.2 查询所有

  • 以树形table展示数据

2.2.1 后端实现

  • 修改 EduSubjectController
package com.czxy.zx.course.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.czxy.zx.course.service.EduSubjectService;
import com.czxy.zx.domain.EduSubject;
import com.czxy.zx.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author txt* @email tanxintong9968@163.com*/
@RestController
@RequestMapping("/subject")
public class EduSubjectController {@Resourceprivate EduSubjectService eduSubjectService;@GetMappingpublic BaseResult findAll() {//1 查询所有QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.orderByAsc("parent_id");List<EduSubject> list = eduSubjectService.list(queryWrapper);//2 处理父子关系List<EduSubject> resultList = new ArrayList<>();Map<String,EduSubject> cache = new HashMap<>();list.forEach(eduSubject -> {// 获得父EduSubject parentEduSubject = cache.get(eduSubject.getParentId());// 如果没有父表示第一层,如果有父追加if(parentEduSubject != null) {// 如果有孩子,判断父对象的集合List<EduSubject> temp = parentEduSubject.getChildren();if(temp == null) {parentEduSubject.setChildren(new ArrayList<>());}// 将孩子添加到父对象的集合中parentEduSubject.getChildren().add(eduSubject);} else {resultList.add(eduSubject);}// 缓存当前cache.put(eduSubject.getId(),eduSubject);});return BaseResult.ok("查询成功", resultList);}}

2.2.2 前端接口

import axios from '@/utils/request'// 查询所有课程科目
export function findAllSub() {return axios.get('/course-service/subject');
}

2.2.3 前端实现

  • 修改 @/views/edu/course/subjectList.vue

<template><div><el-tablev-loading="listLoading":data="subjectList"borderfithighlight-current-rowstyle="width: 100%;"row-key="title":tree-props="{children: 'children'}"><el-table-column label="科目名称" prop="title" align="center" width="200"></el-table-column><el-table-column label="排序" prop="sort" width="80px" min-width="50px"></el-table-column><el-table-column label="添加时间" width="200px" align="center"><template slot-scope="{row}"><span>{{ row.gmtCreate | parseTime('{y}-{m}-{d} {h}:{i}') }}</span></template></el-table-column><el-table-column label="更新时间" width="200px" align="center"><template slot-scope="{row}"><span>{{ row.gmtModified | parseTime('{y}-{m}-{d} {h}:{i}') }}</span></template></el-table-column><el-table-column label="操作" align="center" class-name="small-padding fixed-width"><template slot-scope="{row,$index}"><el-button type="primary" size="mini">修改</el-button><el-button v-if="row.status!='deleted'" size="mini" type="danger" >删除</el-button></template></el-table-column></el-table></div>
</template><script>
import { findAllSub } from '@/api/edu/course'export default {data() {return {subjectList: [] ,listLoading: false,}},methods: {async findAllSubject() {  // 查询所有this.listLoading = truelet { data } = await findAllSub()this.subjectList = datathis.listLoading = false}},mounted() {this.findAllSubject()},
}
</script><style></style>

2.3 导入科目

2.3.1 需求

2.3.2 前端

  • 使用 upload组件

        <!-- 文件上传 --><el-uploadclass="upload-demo":action="updateUrl":limit="1":on-exceed="handleExceed":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleSuccess":file-list="fileList"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传xls或xlsx文件,且不超过500kb</div></el-upload>
    
  • 声明变量

      data() {return {fileList: [],     //上传文件列表updateUrl: process.env.VUE_APP_BASE_API + '/course-service/subject/upload',   //上传路径}},
    
  • 编写处理函数

    handleExceed(files, fileList) {   // 超出个数限制this.$message.warning(`当前选择1个文件`);},beforeUpload(file) {      // 上传文件之前// 是否是 xlsx 文件(2003)const isXlsx = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'// 是否是 xls 文件(2010)const isXls = file.type === 'application/vnd.ms-excel'const isLt2M = file.size / 1024 / 1024 < 2;if (!isXlsx && !isXls) {this.$message.error('上传文件不是excel文件!');}if (!isLt2M) {this.$message.error('上传文件大小不能超过 2MB!');}return (isXlsx || isXls) && isLt2M;},handleRemove(file, fileList) {  // 文件列表移除文件console.log(file, fileList);},handleSuccess(response, file, fileList) { // 文件上传成功// 成功提示this.$message.success(response.message)// 刷新this.findAllSubject()}
    

2.3.2 前端:完整版

<template><div><el-tablev-loading="listLoading":data="subjectList"borderfithighlight-current-rowstyle="width: 100%;"row-key="title":tree-props="{children: 'children'}"><el-table-column label="科目名称" prop="title" align="left" width="200"></el-table-column><el-table-column label="排序" prop="sort" width="80px" min-width="50px"></el-table-column><el-table-column label="添加时间" width="200px" align="center"><template slot-scope="{row}"><span>{{ row.gmtCreate | parseTime('{y}-{m}-{d} {h}:{i}') }}</span></template></el-table-column><el-table-column label="更新时间" width="200px" align="center"><template slot-scope="{row}"><span>{{ row.gmtModified | parseTime('{y}-{m}-{d} {h}:{i}') }}</span></template></el-table-column><el-table-column label="操作" align="center" class-name="small-padding fixed-width"><template slot-scope="{row}"><el-button type="primary" size="mini">修改</el-button><el-button v-if="row.status!='deleted'" size="mini" type="danger" >删除</el-button></template></el-table-column></el-table><!-- 文件上传 --><el-uploadclass="upload-demo":action="updateUrl":limit="1":on-exceed="handleExceed":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleSuccess":file-list="fileList"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传xls或xlsx文件,且不超过500kb</div></el-upload></div>
</template><script>
import { findAllSub } from '@/api/edu/course'export default {data() {return {subjectList: [] ,listLoading: false,fileList: [],     //上传文件列表updateUrl: process.env.VUE_APP_BASE_API + '/course-service/subject/upload',   //上传路径}},methods: {async findAllSubject() {  // 查询所有this.listLoading = truelet { data } = await findAllSub()this.subjectList = datathis.listLoading = false},handleExceed(files, fileList) {   // 超出个数限制this.$message.warning(`当前选择1个文件`);},beforeUpload(file) {      // 上传文件之前// 是否是 xlsx 文件(2003)const isXlsx = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'// 是否是 xls 文件(2010)const isXls = file.type === 'application/vnd.ms-excel'const isLt2M = file.size / 1024 / 1024 < 2;if (!isXlsx && !isXls) {this.$message.error('上传文件不是excel文件!');}if (!isLt2M) {this.$message.error('上传文件大小不能超过 2MB!');}return (isXlsx || isXls) && isLt2M;},handleRemove(file, fileList) {  // 文件列表移除文件console.log(file, fileList);},handleSuccess(response, file, fileList) { // 文件上传成功// 成功提示this.$message.success(response.message)// 刷新this.findAllSubject()}},mounted() {this.findAllSubject()},
}
</script><style></style>

2.3.4 后端

1) 完善JavaBean

package com.czxy.zx.domain;import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** 课程科目(EduSubject)表实体类** @author txt*/
@Data
@TableName("edu_subject")
public class EduSubject{@TableId(type = IdType.ASSIGN_UUID)//课程科目IDprivate String id;//科目名称private String title;//父IDprivate String parentId;//排序字段private Integer sort;//创建时间@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")@TableField(fill = FieldFill.INSERT)private Date gmtCreate;//更新时间@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")@TableField(fill = FieldFill.INSERT)private Date gmtModified;@TableField(exist = false)private List<EduSubject> children = new ArrayList<>();}

2)填充数据处理类

package com.czxy.zx.course.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.util.Date;/*** @author txt* @email tanxintong9968@163.com*/
@Component
public class SubjectMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 创建时间this.setFieldValByName("gmtCreate",new Date(), metaObject);// 修改时间this.setFieldValByName("gmtModified",new Date() , metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {// 修改时,填充的内容this.setFieldValByName("gmtModified",new Date() , metaObject);}
}

3)service:通过title查询

  • 接口

    package com.czxy.zx.course.service;import com.baomidou.mybatisplus.extension.service.IService;
    import com.czxy.zx.domain.EduSubject;/*** @author txt* @email tanxintong9968@163.com*/
    public interface EduSubjectService extends IService<EduSubject> {/*** 通过title查询* @param title* @return*/EduSubject findByTitle(String title);
    }
  • 实现类

    package com.czxy.zx.course.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.czxy.zx.course.mapper.EduSubjectMapper;
    import com.czxy.zx.course.service.EduSubjectService;
    import com.czxy.zx.domain.EduSubject;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;/*** @author txt* @email tanxintong9968@163.com*/
    @Service
    @Transactional
    public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {@Overridepublic EduSubject findByTitle(String title) {QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("title", title);EduSubject eduSubject = baseMapper.selectOne(queryWrapper);return eduSubject;}
    }

4)controller:上传

 /*** 文件上传* @param file* @return*/@PostMapping("/upload")public BaseResult upload(MultipartFile file) {try {// 解析excelEasyExcel.read(file.getInputStream(), UploadSubjectVo.class, eduSubjectListener).sheet(0).doRead();return BaseResult.ok("上传成功");} catch (IOException e) {return BaseResult.error("上传失败");}}

5)excel内容封装类

package com.czxy.zx.course.upload;import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;/*** @author txt* @email tanxintong9968@163.com*/
@Data
public class UploadSubjectVo {@ExcelProperty("一级分类")private String oneLevel;@ExcelProperty("二级分类")private String twoLevel;}

6)上传内容处理类

package com.czxy.zx.course.upload;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.czxy.zx.course.service.EduSubjectService;
import com.czxy.zx.domain.EduSubject;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** @author txt* @email tanxintong9968@163.com*/
@Component
public class EduSubjectListener extends AnalysisEventListener<UploadSubjectVo> {@Resourceprivate EduSubjectService eduSubjectService;@Overridepublic void invoke(UploadSubjectVo uploadSubjectVo, AnalysisContext analysisContext) {// 1. 处理一级// 1.1 查询一级EduSubject oneSubject = eduSubjectService.findByTitle(uploadSubjectVo.getOneLevel());// 1.2 保存一级if(oneSubject == null) {oneSubject = new EduSubject();oneSubject.setTitle(uploadSubjectVo.getOneLevel());oneSubject.setSort(0);oneSubject.setParentId("0");        // 一级默认0eduSubjectService.save(oneSubject);}// 2. 处理二级// 2.1 查询二级EduSubject twoSubject = eduSubjectService.findByTitle(uploadSubjectVo.getTwoLevel());// 2.2 保存二级if(twoSubject == null) {twoSubject = new EduSubject();twoSubject.setTitle(uploadSubjectVo.getTwoLevel());twoSubject.setSort(0);twoSubject.setParentId(oneSubject.getId()); //二级的父ID为一级的IDeduSubjectService.save(twoSubject);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}
}

3.POI入门

3.1 POI 概述

3.1.1 简介

​ Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

功能 描述
HSSFWorkBook 提供读写Microsoft Excel格式档案的功能,xls文档
XSSFWorkBook 提供读写Microsoft Excel OOXML格式档案的功能,xlsx文件
HWPF 提供读写Microsoft Word格式档案的功能
HSLF 提供读写Microsoft PowerPoint格式档案的功能
HDGF 提供读写Microsoft Visio格式档案的功能

3.1.2 官网

http://poi.apache.org/

3.2 入门案例

3.2.1 环境搭建

  • 创建项目:

  • 修改pom

    <dependencies><!--xls--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version></dependency><!--xlsx--><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.9</version></dependency><!--日期格式化工具--><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.1</version></dependency><!--test--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
    

3.2.2 xls文件写操作

  • excel2003 文件扩展名为 xls
  • 名词:
    • 工作簿:一个excel文件,就是一个工作簿
    • 工作表:一个工作簿中,可以所有多个工作表Sheet
    • 行:每一个工作表,包含多行row
    • 单元格:每行有多个单元格Cell组成。
package com.zx.poi;import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import org.junit.Test;import java.io.FileOutputStream;
import java.io.IOException;public class Excel03Test {@Testpublic void testWrite03() throws IOException {// 创建新的Excel 工作簿Workbook workbook = new HSSFWorkbook();// 在Excel工作簿中建一工作表,其名为缺省值 Sheet0//Sheet sheet = workbook.createSheet();// 如要新建一名为"信息统计"的工作表,其语句为:Sheet sheet = workbook.createSheet("信息统计");// 创建行(row 1)Row row1 = sheet.createRow(0);// 创建单元格(col 1-1)Cell cell11 = row1.createCell(0);cell11.setCellValue("今日人数");// 创建单元格(col 1-2)Cell cell12 = row1.createCell(1);cell12.setCellValue(666);// 创建行(row 2)Row row2 = sheet.createRow(1);// 创建单元格(col 2-1)Cell cell21 = row2.createCell(0);cell21.setCellValue("统计时间");//创建单元格(第三列)Cell cell22 = row2.createCell(1);String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell22.setCellValue(dateTime);// 新建一输出文件流(注意:要先创建文件夹)FileOutputStream out = new FileOutputStream("d://zx/a.xls");// 把相应的Excel 工作簿存盘workbook.write(out);// 操作结束,关闭文件out.close();System.out.println("文件生成成功");}
}

3.2.3 xlsx 文件写操作

excel2007+ 文件扩展名为 xlsx

package com.zx.poi;import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
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.joda.time.DateTime;
import org.junit.Test;import java.io.FileOutputStream;
import java.io.IOException;public class Excel07Test {@Testpublic void testWrite07() throws IOException {// 创建新的Excel 工作簿Workbook workbook = new XSSFWorkbook();// 在Excel工作簿中建一工作表,其名为缺省值 Sheet0//Sheet sheet = workbook.createSheet();// 如要新建一名为"信息统计"的工作表,其语句为:Sheet sheet = workbook.createSheet("信息统计");// 创建行(row 1)Row row1 = sheet.createRow(0);// 创建单元格(col 1-1)Cell cell11 = row1.createCell(0);cell11.setCellValue("今日人数");// 创建单元格(col 1-2)Cell cell12 = row1.createCell(1);cell12.setCellValue(666);// 创建行(row 2)Row row2 = sheet.createRow(1);// 创建单元格(col 2-1)Cell cell21 = row2.createCell(0);cell21.setCellValue("统计时间");//创建单元格(第三列)Cell cell22 = row2.createCell(1);String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell22.setCellValue(dateTime);// 新建一输出文件流(注意:要先创建文件夹)FileOutputStream out = new FileOutputStream("d://zx/b.xlsx");// 把相应的Excel 工作簿存盘workbook.write(out);// 操作结束,关闭文件out.close();System.out.println("文件生成成功");}
}

3.2.4 xls 文件读操作

// xls 2003 文件读操作@Testpublic void testXlsRead() throws Exception {//1 确定文件流FileInputStream is = new FileInputStream("D:\\xml\\user.xls");//2 开始读// 2.1 工作簿HSSFWorkbook workbook = new HSSFWorkbook(is);// 2.2 工作表HSSFSheet sheet = workbook.getSheet("用户表");int rowStart = sheet.getFirstRowNum();      //第一行索引号(从0开始)int rowEnd = sheet.getLastRowNum();         //最后一行的索引号(从0开始)// 2.3 行for(int i = rowStart ; i <= rowEnd ; i ++) {HSSFRow row = sheet.getRow(i);int cellStart = row.getFirstCellNum();      //第一列的索引号(从0开始)int cellEnd = row.getLastCellNum() ;        //最后一列的编号(从1开始)// 2.4 列for(int c = cellStart; c < cellEnd ; c++) {HSSFCell cell = row.getCell(c);
//                System.out.println(cell.getCellType());if(cell.getCellType() == Cell.CELL_TYPE_STRING) {// 字符串System.out.print(row.getCell(c).getStringCellValue() + ", ");}if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {// 字符串System.out.print(row.getCell(c).getNumericCellValue() + ", ");}}System.out.println();}// 3 释放资源is.close();}

3.2.5 xlsx 文件读操作

 // xlsx 2007 文件读操作@Testpublic void testXlsxRead() throws Exception {//1 确定文件流FileInputStream is = new FileInputStream("D:\\xml\\user.xlsx");//2 开始读// 2.1 工作簿Workbook workbook = new XSSFWorkbook(is);// 2.2 工作表Sheet sheet = workbook.getSheet("用户表");int rowStart = sheet.getFirstRowNum();      //第一行索引号(从0开始)int rowEnd = sheet.getLastRowNum();         //最后一行的索引号(从0开始)// 2.3 行for(int i = rowStart ; i <= rowEnd ; i ++) {Row row = sheet.getRow(i);int cellStart = row.getFirstCellNum();      //第一列的索引号(从0开始)int cellEnd = row.getLastCellNum() ;        //最后一列的编号(从1开始)// 2.4 列for(int c = cellStart; c < cellEnd ; c++) {Cell cell = row.getCell(c);
//                System.out.println(cell.getCellType());if(cell.getCellType() == Cell.CELL_TYPE_STRING) {// 字符串System.out.print(row.getCell(c).getStringCellValue() + ", ");}if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {// 字符串System.out.print(row.getCell(c).getNumericCellValue() + ", ");}}System.out.println();}// 3 释放资源is.close();}

3.2.6 读取不同类型的数据

@Test
public void testRead07() throws Exception{InputStream is = new FileInputStream("d:/0704.xlsx");Workbook workbook = new XSSFWorkbook(is);Sheet sheet = workbook.getSheetAt(0);// 读取第一行第一列Row row = sheet.getRow(0);Cell cell1 = row.getCell(0);Cell cell2 = row.getCell(1);// 输出单元内容System.out.println(cell1.getStringCellValue());System.out.println(cell2.getNumericCellValue());// 操作结束,关闭文件is.close();
}

end

好啦,以上就是本期全部内容,能看到这里的人呀,都是能人

十年修得同船渡,大家一起点关注。

我是话里人,感谢各位【能人】的:点赞收藏评论,我们下期见!

各位能人们的支持就是话里人前进的巨大动力~

注:如果本篇Blog有任何错误和建议,欢迎能人们留言!

vue-element-admin-master 在线教育 - 【4】你用 POI,我已经用 EasyExcel 了+课程科目管理相关推荐

  1. Vue Element Admin 使用mock模块模拟数据

    Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路.通过预先跟服务器端约定好的接口,模拟请求数据甚至逻辑,能够让前端开发更加独立自主,不会被服务端的开发所阻塞. vue-elem ...

  2. vue+element+admin(初始化项目)

    2022.10.17我接触到了vue+element+admin的使用,首先要安装node.jshttps://nodejs.org/zh-cn/download/.和githttps://git-s ...

  3. vue element admin登录方式切换(密码登录或短信登录)

    显示结果: 具体代码可以根据vue element admin源码进行更改,下面是页面代码 <el-form ref="loginForm" :model="log ...

  4. 钉钉爆火背后,真正的在线教育机构过得怎么样?已有 1 家倒闭

    作者丨赵家云 本文经授权转载自猎云网( ID:ilieyun) 因为疫情,全国各地学校开学日期一拖再拖,在线教育需求量暴涨.在此期间,作为一款在线办公软件,钉钉却屡次被推上热搜,迅速在教育圈中走红,让 ...

  5. 【前端】Vue+Element UI案例:通用后台管理系统-代码总结(已开源)

    文章目录 前言 项目文件目录 api mockServe home.js permission.js index.js mock.js user.js assert components Common ...

  6. 后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例

    登录功能描述: 前端输入对应的用户信息 ,在用户输入邮箱后 点击发送按钮给邮箱发送验证码,拿取到验证填完之后,点击登录按钮给后端发送请求 ,后端接收到请求之后 ,第一步校验验证码,第二步校验用户名和密 ...

  7. Vue Element Admin 用mock模块模拟数据

    步骤简单 一  在 src/api/charts 中添加接口 , 方法名为 getindexMock  import request from '@/utils/request'export func ...

  8. 前后端分离项目,vue+uni-app+php+mysql在线教育视频点播小程序系统 开题报告

      毕业论文 基于Vue.js视频点播小程序系统 开题报告 学    院: 专    业: 年    级: 学生姓名: 指导教师: 黄菊华   XXXX大学本科生毕业论文(设计)开题报告书 姓   名 ...

  9. vue element admin中发送请求和设置loading效果

    需求:在表格数据加载完成前进入loading显示数据正在加载,数据加载完成后取消loading效果,axios的超时处理和异常的处理之后进行取消loading效果. 小编接下来就根据这个这个需求进行分 ...

  10. Vue Element Admin 添加侧边栏以及他的页面

    1. 在 /src/views/ 下添加需要的页面 2. 配置路由器 router 中的路由表 routes,分为 constantRoutes 和 asyncRoutes. 将路由的配置信息添加进路 ...

最新文章

  1. 现在上学有点赛博朋克内味儿了
  2. highcharts常用配置说明
  3. 【数字信号处理】 第二章、时域中的离散时间信号
  4. jedis对redis键加锁+解锁+事务提交
  5. 如何成为一名有效的软件工程师
  6. 在星辰世界的guandan
  7. 工信部:2021年1-2月锂电池产量29.5亿只
  8. Tornado web开发之简单文件上传
  9. IBM Systems Director VMControl资源生命周期管理,第2部分
  10. 中国轨道交通设备行业建设投资规模及十四五产量趋势研究报告2021-2027年版
  11. window.history详细解析
  12. 三维GIS的困境与出路
  13. 阿里云认证有用吗?阿里云证书含金量及如何获得
  14. 数字系统设计(FPGA)课程设计: 多功能数字钟
  15. Python数据分析案例07——二手车估价(机器学习全流程,数据清洗、特征工程、模型选择、交叉验证、网格搜参、预测储存)
  16. SDWebImage如何避免复用
  17. “三屏融合”或比“三网融合”更不现实
  18. Halo——zcash新的零知识证明机制,无需Trusted Setup
  19. ERP之工单应发料数
  20. 程序员的七夕浪漫时刻

热门文章

  1. 妄想山海测试服下载for android,妄想山海测试服
  2. 鸿蒙系统背后的故事,华为“鸿蒙”刷屏背后,这7本书是中国人的终极浪漫
  3. ps滑动鼠标放大缩小
  4. OpenHarmony release3.1版本启动子系统功能分析
  5. 计算机鼠标左键不起作用,电脑鼠标左键不能用怎么办
  6. python记录鼠标和键盘操作并重复_Python模拟鼠标和键盘操作实现重复性操作
  7. 打印机扫描功能不见了_打印机扫描文件找不到路径怎么办?
  8. 为什么计算机编程以英语为主,为什么英语对于编程来说非常重要
  9. itunes不能读取iPhone的内容,请前往iPhone“偏好设置”的“摘要”选项卡,然后单击“恢复”
  10. Java基于POI来给导出的Excel动态添加水印