EasyPoi与SpringMVC

一、springMVC对于easyPOI的支持

咱们现在开发前端都是直接使用SpringMVC,因此,EasyPoi也直接提供了对SpringMVC的支持!
要想操作excel表格的导入导出,只需要引入easypoi就可以简单的操作
以下为官方的介绍:
easypoi view 项目是为了更简单的方便搭建在导出时候的操作,利用spring mvc 的view 封装,更加符合spring mvc的风格 view下面包括多个 view的实现
EasypoiBigExcelExportView 大=数据量导出
EasypoiMapExcelView= map 列表导出
EasypoiPDFTemplateV=iew pdf导出
EasypoiSingleE=xcelView 注解导出
EasypoiTemplateExcelView 模板导出
EasypoiTemplateWordView word模板导出
MapGraphExcelView 图表导出
view的是使用方法大同小异,都有一个对应的bean,里面保护指定的参数常量 同意用modelmap.put(‘常量参数名’,‘值’)就可以,最后返回这个view名字
注解目录扫描的时候加上 cn.afterturn.easypoi.view 就可以使用了

二、使用方式

导入jar包



  cn.afterturn
  easypoi-base
  3.2.0


  cn.afterturn
  easypoi-web
  3.2.0


  cn.afterturn
  easypoi-annotation
  3.2.0

  • 查看easyPOI文档.

三、导出

在浏览器点击导出从数据库导出数据
实体类employee,department

在需要导出的字段上打上注解
一些注解的语法:
1.年龄_emp
必需保证类的ExcelTarget的id是emp才会展示
2.format = “yyyy-MM-dd”:日期的格式
注:如果数据库是varchar,还需要配置databaseFormat
3.replace={“男_true”,“女_false”}
如果值是true,那么展示男,如果是false,则在页面展示女
4.@ExcelEntity(id=“emp”):对应另一个关连对象
id是为这个实体取一个名称,和关连的导出对应
5.type = 2 :代表这是一个图片展示
6.如果需要在指定表显示指定的字段需要给表取名字
在这里插入图片描述在这里插入图片描述
然后想要的字段就在设置名字的时候加上别名,比如:
EasyPoi与SpringMVC_第1张图片详细注解参考文档

@Entity
@Table(name="employee")
public class Employee extends BaseDomain {
    @Excel(name = "用户名")
    private String username;
    private String password;
    @Excel(name = "邮件",width = 25)
    private String email;
    @Excel(name = "年纪")
    private Integer age;
    @Excel(name = "头像",type = 2,width = 10 , height = 20)
    //加入头像字段
    private String headImage;

    @ExcelEntity
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
    private Department department;
    省略getset...
}

1.准备导出页面,以实体类employee为例
在高级查询条中加入导出功能

<%--高级查询查询条--%>
        
用户名: 邮件: 部门: <%--点击查询触发js 绑定函数 发送请求数据 高级查询条件封装成对象--%> 查询

为什么需要高级查询?

  • 不是每次都要将所有的员工导出,所以是在高级查询的查询条加入导出按钮
  • 点击导出会将查询条件也传到后台,后台按查询条件查出数据并且导出
    在这里插入图片描述
    点击导出
    EasyPoi与SpringMVC_第2张图片
    controller层
@RequestMapping("/download")
public String download(EmployeeQuery query,ModelMap map, HttpServletRequest request) {
    List list = employeeService.findByQuery(query);
    //搞定路径问题
    list.forEach(e -> {
        String realPath = request.getServletContext().getRealPath("");
        e.setHeadImage(realPath+e.getHeadImage());
    });

    ExportParams params = new ExportParams("员工数据", "测试", ExcelType.XSSF);
    params.setFreezeCol(2); //设置固定列
    map.put(NormalExcelConstants.DATA_LIST, list); // 数据集合
    map.put(NormalExcelConstants.CLASS, Employee.class);//导出实体
    map.put(NormalExcelConstants.PARAMS, params);//参数
    map.put(NormalExcelConstants.FILE_NAME, "员工信息");//文件名称
    return  NormalExcelConstants.EASYPOI_EXCEL_VIEW;
}

点击导出报错
EasyPoi与SpringMVC_第3张图片
原因是配置了视图解析器,响应的时候会自动使用我们的视图解析器,自动加上后缀
解决方法:
applicationContext-mvc.xml注解目录扫描的时候加上 cn.afterturn.easypoi.view

 




  1. 配置完成如果还是报错,点击导出的时候每次报错classNotfound ExportParams
    但是普通测试的时候,并没有报错,所以可能只是在tomcat服务器运行时的错误
    在这里插入图片描述
  2. 正常情况tomcat会将jar包自动放到项目下,但是有时候不会,右边会出现很多没有放过去的jar包,这时候服务器运行就会始终找不到,点击放入
    EasyPoi与SpringMVC_第4张图片
  3. 完成导出功能
    完整代码
    得到图片的真实路径
//到处excel表格   /employee/download
        @RequestMapping("/download")
        public String download(EmployeeQuery query,ModelMap map, HttpServletRequest request) {
            System.out.println("=================================adasd");
            List list = iEmployeeService.findByQuery(query);
            //修改当前员工的头像路径 -> 真实路径
            String realPath = request.getServletContext().getRealPath("");
            list.forEach(e->{
                e.setHeadImage(realPath + e.getHeadImage());
            });

            ExportParams params = new ExportParams("员工数据", "测试", ExcelType.XSSF);
            //params.setFreezeCol(2); 冻结相应的列
            map.put(NormalExcelConstants.DATA_LIST, list); // 数据集合
            map.put(NormalExcelConstants.CLASS, Employee.class);//导出实体
            map.put(NormalExcelConstants.PARAMS, params);//参数
            map.put(NormalExcelConstants.FILE_NAME, "employee");//文件名称
            //return "easypoiExcelView";
            return NormalExcelConstants.EASYPOI_EXCEL_VIEW;//View名称
        }

EasyPoi与SpringMVC_第5张图片

四、导入

  • 准备导入页面
  • 注意要上传文件时必须加上
    method=“post” enctype=“multipart/form-data”
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title
    <%@include file="/WEB-INF/views/head.jsp" %>



${count}

ImportController层的准备

@Controller
@RequestMapping("/import")
public class ImportController {

    @RequestMapping("/index")
    public String index(){
        System.out.println("进入导入功能");
        return "import";
    }
     @RequestMapping("/xlsx")
    public String importEmployee(MultipartFile xlsxFile,HttpServletResponse response) throws Exception {
    
    return "import";
    }

五、没有验证的导入

从外部将数据导入数据库
controller层代码

@RequestMapping("/xlsx")
public String importEmployee(MultipartFile xlsxFile) throws Exception {
    InputStream inputStream = xlsxFile.getInputStream();
    ImportParams params = new ImportParams();
    //没有注释之前查出来是null
    params.setTitleRows(1);

    List list = ExcelImportUtil.importExcel(
            inputStream,
            Employee.class, params);
list.forEach(u -> u);

    return "import";
}
  • xlsxFile.getInputStream();得到导入的文件流
  • ImportParams params = new ImportParams();创建导入的参数设置对象
    可以设置导入时的一些参数,和判断等等
  • 不开启验证得到的是所有数据
    ExcelImportUtil.importExcel
    注意导入的excel字段名称要和实体类的注解excel的名称一致不然封装不了
    在这里插入图片描述
    开始测试,然后开启疯狂报错模式
@RequestMapping("/xlsx")
public String importEmployee(MultipartFile xlsxFile) throws Exception {
    InputStream inputStream = xlsxFile.getInputStream();
    ImportParams params = new ImportParams();
    //没有注释之前查出来是null
    params.setTitleRows(1);

    List list = ExcelImportUtil.importExcel(
            inputStream,
            Employee.class, params);
	list.forEach(u -> iEmployeeService.save(u));
    return "import";
}

在这里插入图片描述
在这里插入图片描述
因为我们在保存时将密码加密了,如果导入的用户密码为空,就会报错
所以在保存时设置初始密码123
继续测试又报错
在这里插入图片描述
个人理解:
我们前台直接添加时,持久层保存都是save方法,没有id可以自动创建,
保存employee时也没有传id为什么就不会报错?因为在封装employee之前jpa会自动去查询到部门,封装到员工对象,然后再保存员工
但是
现在使用的是easypoi,能自动识别吗?
不能,只通过一个部门的名称,不能封装成对象存入employee对象,id都为null,现在部门就只存了一个部门名字
employee对象中,就只有一个id为空的部门对象,只根据这个部门名称并不能确定部门对象
在这里插入图片描述
我们表中有什么数据,对应得上实体类的字段,就可以存入
Easypoi只能封装对象的字段,和对应的另一个实体类对象字段,而且是打了注解的才可以

  • 解决方法
    1.添加初始密码
    2.将部门根据名称查出

思路整理

  • 获取前台文件流MultipartFile
  • 创建导入参数设置对象ImportParams
  • 得到文件输入流inputStream
  • ImportParams 设置参数
  • ExcelImportUtil.importExce得到导入数据
  • 更改初始密码
  • 存入部门
@RequestMapping("/xlsx")
    public String importEmployee(MultipartFile xlsxFile) throws Exception {

        InputStream inputStream = xlsxFile.getInputStream();
        ImportParams params = new ImportParams();
        //没有注释之前查出来是null
        params.setTitleRows(1);;
        List list = ExcelImportUtil.importExcel(
                inputStream,
                Employee.class, params);


        for (Employee e : list) {
            e.setPassword("123");
            //通过员工的
            if (e.getDepartment()!=null){
                //Department{name='IT部', id=null}  现在部门的id是空,前台导入的时候不能确定部门,报错
                //通过名字将部门查出来,再存入到这个员工对象中
                System.out.println(iDepartmentService);
                Department department = iDepartmentService.findByName(e.getDepartment().getName());
                e.setDepartment(department);
            }
            iEmployeeService.save(e);
        }
        return "import";
    }

基本的导入功能完成,但是用户名重复,年龄等等不符合标准
所以需要验证

六、加入验证功能

实体类注解

@Entity
@Table(name="employee")
public class Employee extends BaseDomain {
    @Excel(name = "用户名")
    @NotBlank(message = "用户名不能为空")
    private String username;

    private String password;
    @Excel(name = "邮件",width = 25)
    private String email;
    @Max(value =60,message = "年纪最大为60岁")
    @Excel(name = "年纪")
    private Integer age;
    @Excel(name = "头像",type = 2,width = 10 , height = 20)
    //加入头像字段
    private String headImage;
}

Controller层启用验证

//设置启用 验证
params.setNeedVerfiy(true);

获得导入的数据

//获取到所有导入的数据
ExcelImportResult result = ExcelImportUtil.importExcelMore(inputStream, Employee.class, params);

注意现在是使用 ExcelImportUtil.importExcelMore获取导入 数据
现在控制层就只将通过验证的数据保存

@RequestMapping("/xlsx")
    public String importEmployee(MultipartFile xlsxFile,HttpServletResponse response) throws Exception {

        InputStream inputStream = xlsxFile.getInputStream();
       /* 获取导入参数*/
        ImportParams params = new ImportParams();
        //没有注释之前查出来是null
        params.setTitleRows(1);
        //设置启用 验证
        params.setNeedVerfiy(true);
        //获取到所有导入的数据
        ExcelImportResult result = ExcelImportUtil.importExcelMore(inputStream, Employee.class, params);
        /*得到成功的数据*/
        for (Employee e : result.getList()) {
            System.out.println(e+"成功的数据===============================");
            e.setPassword("123");
            //通过员工的
            if (e.getDepartment()!=null){
                //Department{name='IT部', id=null}  现在部门的id是空,前台导入的时候不能确定部门,报错
                //通过名字将部门查出来,再存入到这个员工对象中
                System.out.println(iDepartmentService);
                Department department = iDepartmentService.findByName(e.getDepartment().getName());
                e.setDepartment(department);
            }
            iEmployeeService.save(e);
        }
        return "import";
    }
  • 基本验证完成,但是用户名重复还是不能解决
  • 导入失败的数据应该单独存起来

七、自定义验证器

1.实现接口
2.确定泛型
3.开启扫描,告诉springMvc这个类
4.通过查询数据库判断是否重复用户名
5.@Component注解 组件 交给spring管理

@Component
public class MyExcelVerifyHandler implements IExcelVerifyHandler {
    //确定泛型
    @Autowired
    private IEmployeeService iEmployeeService;
    @Override
    public ExcelVerifyHandlerResult verifyHandler(Employee employee) {
        ExcelVerifyHandlerResult result = new ExcelVerifyHandlerResult();
        //判断是否重名,如果用户名能用,返回true
        Boolean bool = iEmployeeService.checkName(employee.getUsername());
        if (!bool){
            result.setMsg("用户名重复了");
            result.setSuccess(false);
            return result;
        }
        /*没有重复就返回true,通过验证*/
        result.setSuccess(true);
        return result;
    }
}

错误文件
easyPOI已经自动将错误文件生成了,直接使用
文件下载功能,直接返回浏览器,下载错误文件

if (result.isVerfiyFail()){
            //错误的文件
            //easyPOI自动已经生成了错误文件
            Workbook wb = result.getFailWorkbook();
            System.out.println(wb);
            //选择文件的类型,从tomcat的conf打开web.xml选择对应的文件类型
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //mime类型
            response.setHeader("Content-disposition", "attachment;filename=error.xlsx");
            //设置不要缓存
            response.setHeader("Pragma", "No-cache");
            OutputStream ouputStream = response.getOutputStream();
            wb.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        }

错误提示也保存了
EasyPoi与SpringMVC_第6张图片
完整controller代码

@RequestMapping("/xlsx")
    public String importEmployee(MultipartFile xlsxFile,HttpServletResponse response) throws Exception {

        InputStream inputStream = xlsxFile.getInputStream();
       /* 获取导入参数*/
        ImportParams params = new ImportParams();
        //没有注释之前查出来是null
        params.setTitleRows(1);
        //设置启用 验证
        params.setNeedVerfiy(true);
        //放入自定义验证
        params.setVerifyHandler(myExcelVerifyHandler);
        //获取到所有导入的数据
        ExcelImportResult result = ExcelImportUtil.importExcelMore(inputStream, Employee.class, params);
        /*得到成功的数据*/
        for (Employee e : result.getList()) {
            System.out.println(e+"成功的数据===============================");
            e.setPassword("123");
            //通过员工的
            if (e.getDepartment()!=null){
                //Department{name='IT部', id=null}  现在部门的id是空,前台导入的时候不能确定部门,报错
                //通过名字将部门查出来,再存入到这个员工对象中
                System.out.println(iDepartmentService);
                Department department = iDepartmentService.findByName(e.getDepartment().getName());
                e.setDepartment(department);
            }
            iEmployeeService.save(e);
        }
        if (result.isVerfiyFail()){
            //错误的文件
            //easyPOI自动已经生成了错误文件
            Workbook wb = result.getFailWorkbook();
            System.out.println(wb);
            //选择文件的类型,从tomcat的conf打开web.xml选择对应的文件类型
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //mime类型
            response.setHeader("Content-disposition", "attachment;filename=error.xlsx");
            //设置不要缓存
            response.setHeader("Pragma", "No-cache");
            OutputStream ouputStream = response.getOutputStream();
            wb.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        }
        return "import";
    }

你可能感兴趣的:(EasyPoi与SpringMVC)