- 【SpringBoot+Mybatis-plus+poi】实现校验导入excel(一)
- 1. 实体(为Mybatis的Generator生成工具生成)
- 2. dao层(为Mybatis的Generator生成工具生成)
- 3. service层(为Mybatis的Generator生成工具生成)
- 3.1. api
- 3.1. impl(内部方法为实现类导入方法工厂的方法)
- 4. 实现类工厂生产实现类导入方法
- 5. mapper层
- 6. 导入工厂
- 6.1. 生产导入
- 7. 校验工厂
- 7.1. 生产校验方式
- 8. 工具类
- 9. pom路径
- 10. controller层
- 11. Generator代码生成工具
- 12. 配置文件yml
- 13. 项目层级
- 14. postman运行方式
- 15. 运行结果(校验失败)
- 16. 运行结果(补上缺失数据,校验成功)
实现校验导入excel,我打算用两章实现:
第一章根据工厂模式(三个工厂:导入工厂、校验工厂和实现类导入方法工厂)和简单的非空校验实现user.xlsx的导入校验;
第二章根据工厂模式和自定义注解实现user.xlsx的导入校验。
首先看一下excel文档:
这里我删掉了部分单元格数据,作为非空校验的导入模板;
校验成功则根据id查询数据库的数据,如果结果为空则新增,否则更新;
校验失败则给对应单元格标红,并在最后一列打印错误信息。
上代码:
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@TableName("t_user")
public class TUser {
private Integer id;
private String name;
private String age;
private String sex;
private String address;
private String contactInformation;
}
2. dao层(为Mybatis的Generator生成工具生成)
import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.example.import1.domain.TUser; import org.apache.ibatis.annotations.Mapper; @Mapper public interface TUserMapper extends baseMapper3. service层(为Mybatis的Generator生成工具生成) 3.1. api{ }
import com.baomidou.mybatisplus.extension.service.IService; import com.example.import1.domain.TUser; public interface IUserService extends IService3.1. impl(内部方法为实现类导入方法工厂的方法){ }
@Service @Slf4j public class UserServiceImpl extends ServiceImpl4. 实现类工厂生产实现类导入方法implements IUserService, ICombineService { @Autowired private TUserMapper userMapper; @Override @Transactional public XSSFWorkbook importExcel(InputStream inputStream) throws IOException { StringBuilder errorString = new StringBuilder(); XSSFWorkbook wb = new XSSFWorkbook(inputStream); Sheet s = wb.getSheetAt(0); int allNums = s.getPhysicalNumberOfRows(); Iimport check = new Userimport(userMapper); //校验 check.checkResult(errorString,wb,s,allNums,inputStream); //导入数据 if (StringUtils.isBlank(errorString)){ check.createData(s, allNums); wb = null; } return wb; } }
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.InputStream;
public interface ICombineService {
XSSFWorkbook importExcel(InputStream inputStream) throws IOException;
}
5. mapper层
6. 导入工厂id, name, age, sex, address, contactInformation
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.InputStream;
public interface Iimport {
void checkResult(StringBuilder errorMsg, XSSFWorkbook wb, Sheet s, int allNums, InputStream inputStream)throws IOException;
void createData(Sheet s, int allNums);
void create(Sheet s, int i);
}
6.1. 生产导入
import com.example.import1.dispose.ICheck;
import com.example.import1.dispose.Iimport;
import com.example.import1.dispose.check.UserCheck;
import com.example.import1.domain.TUser;
import com.example.import1.mapper.TUserMapper;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Userimport implements Iimport {
private final DataFormatter DATAFORMATTER = new DataFormatter();
//excel起始校验行下标
private static final int START_INDEX = 1;
//excel错误信息下标
private static final int ERROR_INDEX = 6;
private final TUserMapper userMapper;
public Userimport(TUserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public void checkResult(StringBuilder errorMsg, XSSFWorkbook wb, Sheet s, int allNums, InputStream inputStream) throws IOException {
//获取默认单元格样式(在第一行创建一个空单元格获取默认样式)
XSSFCellStyle orgSty = (XSSFCellStyle) s.getRow(0).createCell(100).getCellStyle();
//设置单元格为文本格式
XSSFDataFormat format = wb.createDataFormat();
orgSty.setDataFormat(format.getFormat("@"));
//错误标红单元格样式
XSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
cellStyle.setDataFormat(format.getFormat("@"));
// 重复数据缓存
List dataList = new ArrayList<>();
ICheck check = new UserCheck();
check.check(s, allNums, errorMsg, cellStyle, dataList, START_INDEX, ERROR_INDEX, DATAFORMATTER, userMapper);
}
@Override
public void createData(Sheet s, int allNums) {
for (int i = START_INDEX; i < allNums; i++) {
Row r = s.getRow(i);
if (r == null) {
continue;
}
// 导入禽流感环境病原学监测信息
create(s, i);
}
}
@Transactional
public void create(Sheet s, int i) {
Row r = s.getRow(i);
TUser user = new TUser();
// id
String id = DATAFORMATTER.formatCellValue(r.getCell(0));
int idInt = Integer.parseInt(id);
TUser userCondition = userMapper.selectById(id);
user.setId(idInt);
// 姓名
String name = DATAFORMATTER.formatCellValue(r.getCell(1));
user.setName(name);
// 年龄
String age = DATAFORMATTER.formatCellValue(r.getCell(2));
user.setAge(age);
// 性别
String sex = DATAFORMATTER.formatCellValue(r.getCell(3));
user.setSex(sex);
// 地址
String address = DATAFORMATTER.formatCellValue(r.getCell(4));
user.setAddress(address);
// 联系方式
String contactInformation = DATAFORMATTER.formatCellValue(r.getCell(5));
user.setContactInformation(contactInformation);
if (null != userCondition) {
userMapper.updateById(user);
}else {
userMapper.insert(user);
}
}
}
7. 校验工厂
import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import java.util.List; public interface ICheck7.1. 生产校验方式{ void check(Sheet s, int allNums, StringBuilder errorString, XSSFCellStyle cellStyle, List dataList, int START_INDEX, int ERROR_INDEX, DataFormatter DATAFORMATTER, M m); }
import com.example.import1.dispose.ICheck; import com.example.import1.mapper.TUserMapper; import com.example.import1.util.CheckoutUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import java.util.List; public class UserCheck implements ICheck{ @Override public void check(Sheet s, int allNums, StringBuilder errorString, XSSFCellStyle cellStyle, List dataList, int START_INDEX, int ERROR_INDEX, DataFormatter dataFormatter, TUserMapper userMapper) { for(int i = START_INDEX; i 8. 工具类 import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFCellStyle; public class CheckoutUtils { public static boolean isNull(String zhName, StringBuilder errorMsg, Cell cell, String cellString, XSSFCellStyle cellStyle, Row r, int i){ //如果为空则增加错误信息 if(StringUtils.isBlank(cellString)) { errorMsg.append(zhName).append("必填; "); setCellStyle(r, i, cell, cellStyle); return false; } CellStyle style = cell.getCellStyle(); if (IndexedColors.RED.getIndex() == style.getFillBackgroundColor()) { cell.setCellStyle(null); } return true; } private static void setCellStyle(Row r, int i, Cell cell, XSSFCellStyle cellStyle) { if (null == cell) { cell = r.createCell(i); } cell.setCellStyle(cellStyle); } }9. pom路径10. controller层4.0.0 org.springframework.boot spring-boot-starter-parent 2.6.2 com.example import1 0.0.1-SNAPSHOT import1 Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web com.baomidou mybatis-plus-boot-starter 3.2.0 com.baomidou mybatis-plus-generator 3.2.0 org.apache.velocity velocity-engine-core 2.0 mysql mysql-connector-java runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.apache.poi poi 4.1.2 org.apache.poi poi-ooxml 4.1.2 org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok import com.example.import1.domain.TUser; import com.example.import1.service.ICombineService; import com.example.import1.service.IUserService; import lombok.extern.slf4j.Slf4j; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @RestController @RequestMapping("/user") @Slf4j public class UserController { @Autowired private IUserService userService; @Autowired private ICombineService combineService; @GetMapping("/query/user") public ResponseEntity11. Generator代码生成工具> queryUser(){ return ResponseEntity.ok(userService.list()); } @PostMapping("/import/user") public ResponseEntity
importExcel(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws IOException { XSSFWorkbook wb = combineService.importExcel(file.getInputStream()); if (wb!=null){ ServletOutputStream outputStream = response.getOutputStream(); wb.write(outputStream); wb.close(); outputStream.close(); } return ResponseEntity.ok(true); } } import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert; import com.baomidou.mybatisplus.generator.config.po.TableFill; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; import com.baomidou.mybatisplus.generator.config.rules.IColumnType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import java.util.ArrayList; import java.util.List; public class MpBatisGenerator { private static String projectPath = null; public static void main(String[] args) { // projectPath = System.getProperty("user.dir"); projectPath = "D:\本地项目\import1"; AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setGlobalConfig(configGlobalConfig()); autoGenerator.setDataSource(configDataSource()); autoGenerator.setStrategy(configStrategyConfig()); autoGenerator.setPackageInfo(configPackageConfig()); // autoGenerator.setCfg(customerConfig()); autoGenerator.execute(); } // private static InjectionConfig customerConfig() { // InjectionConfig config = new InjectionConfig() { // @Override // public void initMap() { // // } // }; // List12. 配置文件ymlfiles = new ArrayList (); // files.add(new FileOutConfig() { // @Override // public String outputFile(TableInfo tableInfo) { // String expand = "c:/dam"; // String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getControllerName()); // return entityFile; // } // }); // config.setFileOutConfigList(files); // return config; // } private static GlobalConfig configGlobalConfig() { GlobalConfig config = new GlobalConfig(); // 是否支持AR模式 config.setActiveRecord(true) // 作者 .setAuthor("wp") // 生成路径 .setOutputDir(projectPath + "/src/test/java/") // .setOutputDir("c:/pms/src/main/java/") // 文件覆盖 .setFileOverride(true) // 主键策略 .setIdType(IdType.AUTO) // 设置生成的service接口的名字的首字母是否为I,例如IEmployeeService .setServiceName("%sService") //开启swagger2模式 .setSwagger2(true) //生成基本的resultMap .setbaseResultMap(true) //生成基本的SQL片段 .setbaseColumnList(true) //生成后打开文件夹 .setOpen(false).setDateType(DateType.ONLY_DATE); return config; } private static DataSourceConfig configDataSource() { DataSourceConfig dsConfig = new DataSourceConfig(); // 设置数据库类型 dsConfig.setDbType(DbType.MYSQL) .setDriverName("com.mysql.cj.jdbc.Driver") .setUrl("jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8") .setUsername("root") .setPassword("root") .setTypeConvert(new MySqlTypeConvert() { // 自定义数据库表字段类型转换【可选】 @Override public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) { System.out.println("转换类型:" + fieldType); if (fieldType.toLowerCase().contains("tinyint")) { return DbColumnType.INTEGER; } return super.processTypeConvert(globalConfig, fieldType); } }); return dsConfig; } private static StrategyConfig configStrategyConfig() { StrategyConfig stConfig = new StrategyConfig(); List tableFillList = new ArrayList (); //如 每张表都有一个创建时间、修改时间 //而且这基本上就是通用的了,新增时,创建时间和修改时间同时修改 //修改时,修改时间会修改, //虽然像Mysql数据库有自动更新几只,但像ORACLE的数据库就没有了, //使用公共字段填充功能,就可以实现,自动按场景更新了。 //如下是配置 // 全局大写命名 stConfig.setCapitalMode(true) // 指定表名 字段名是否使用下划线 //.setDbColumnUnderline(true) // 数据库表映射到实体的命名策略 .setNaming(NamingStrategy.underline_to_camel) //.setTablePrefix("tbl_") // 生成的表 .setInclude(new String[]{ "t_user" }) .setEntityBooleanColumnRemoveIsPrefix(false) // 自定义实体,公共字段 .setTableFillList(tableFillList); return stConfig; } private static PackageConfig configPackageConfig() { PackageConfig pkConfig = new PackageConfig(); pkConfig.setParent("com.example.import1") //dao .setMapper("dao") //service .setService("service") //controller .setController("controller") .setEntity("entity") //mapper.xml .setXml("mapper"); return pkConfig; } } server: port: 8546 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/demo username: root password: root # MyBatis配置 mybatis-plus: # 搜索指定包别名 typeAliasesPackage: com.example.import1.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper*Mapper.xml logging: level: com.example: debug13. 项目层级 14. postman运行方式 15. 运行结果(校验失败) 16. 运行结果(补上缺失数据,校验成功)
本章对于SpringBoot+Mybatis-plus+poi实现导入校验就完成了,当我们有几个不同类型的单元格导入的情况下,可以实现实现类工厂导入方法,使用校验工厂和导入工厂分别生产对应类型的校验方法和导入方法,以完成对新增其他类型excel的导入校验。
下一章将本章的非空校验改为自定义注解+反射实现对excel表格校验。
纯手打,技术有限,请各位大佬批评指正,谢谢!



