①自定义注解
package cn.xgl.easypoi;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Target 表示指定当前自定义注解使用的目标
* ElementType.FIELD 表示使用在成员变量上
* ElementType.TYPE 表示使用在类或者接口上
* ElementType.METHOD 表示使用在方法上
* @Retention 指定自定义注解的对象的生命周期
* @Constraint 指定当前自定义注解的验证规则的实现类
* validatedBy 表示被谁验证
*/
//用于指定使用范围,该处限定只能在字段上使用
@Target(ElementType.FIELD)
//运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//validatedBy被谁验证--->实现类字节码文件
@Constraint(validatedBy = DeptNameNotNullValidator.class)
public @interface DeptNameNotNull {
String message() default "所属部门不能为空!";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
②自定义注解的校验规则实现类
package cn.xgl.easypoi;
import cn.xgl.domain.Department;
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* @author Bear
* 自定义验证器
* DeptNameNotNull 注解类型
* Department 字段类型
*/
public class DeptNameNotNullValidator implements ConstraintValidator<DeptNameNotNull, Department> {
/**
* 初始化
* @param deptNameNotNull
*/
@Override
public void initialize(DeptNameNotNull deptNameNotNull) {
System.out.println("验证器初始化......");
}
/**
* 验证规则
* @param department
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(Department department, ConstraintValidatorContext constraintValidatorContext) {
System.out.println("部门验证-->"+department);
//部门为null,无法验证部门名称
if(department == null){
return true;
}
//department.getId()>0 前端传来的参数
if( department.getId()!=null && department.getId()>0){
return true;
}
//部门名称为null 或 "" 返回false,否则true--->已经填写了部门名称
return StringUtils.isNotBlank(department.getName());
}
}
③在字段上添加注解@DeptNameNotNull
/**员工与部门的关系,单项多对一 @NotNull(message = "所属部门不能为null")*/
@DeptNameNotNull
/**导出关联对象的属性值*/
@ExcelEntity
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
@JsonIgnoreProperties(value = {"hibernateLazyInitializer","handler","fieldHandler"})
private Department department;
④Controller层代码:导入成功保存数据,失败则让用户下载更改后再次上传
package cn.xgl.controller;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
import cn.xgl.domain.Department;
import cn.xgl.domain.Employee;
import cn.xgl.service.IDepartmentService;
import cn.xgl.service.IEmployeeService;
import cn.xgl.shiro.MD5Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* @author bear
*/
@Controller
@RequestMapping("/import")
public class ImportController {
@Autowired
private IEmployeeService employeeService;
@Autowired
private IDepartmentService departmentService;
@Autowired
private IExcelVerifyHandler<Employee> uniqueUserameVerifyHandler;
/**
* 跳转至导入页面
* @return
*/
@RequestMapping("/index")
public String index(){
return "employee/empimport";
}
/**
* 处理Excel导入数据
* @param excelFile
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping("/importExcel")
public String importExcel(MultipartFile excelFile, HttpServletRequest request, HttpServletResponse response) throws Exception {
ImportParams params = new ImportParams();
params.setHeadRows(1);//头占1行
params.setTitleRows(1);//标题占1行
//开启验证
params.setNeedVerfiy(true);
//告诉easypoi我们自定义的验证器--->用户名是否唯一
params.setVerifyHandler(uniqueUserameVerifyHandler);
//将excel导入到内存中
//List<Employee> list = ExcelImportUtil.importExcel(excelFile.getInputStream(), Employee.class, params);
//具有验证功能的导入
ExcelImportResult<Employee> result = ExcelImportUtil.importExcelMore(excelFile.getInputStream(), Employee.class, params);
result.getList().forEach(e-> System.out.println("成功的数据--->"+e)); //导入成功的数据
result.getFailList().forEach(e-> System.out.println("失败的数据--->"+e));//导入失败的数据
//将内存中的list保存至数据库-->验证成功的
result.getList().forEach(e->{
//不能保存一个临时状态的对象(部门)org.hibernate.TransientPropertyValueException: object references an unsaved transient instance
//解决通过部门名称查询部门
Department dept = departmentService.findDeptByName(e.getDepartment().getName());
e.setDepartment(dept);
e.setPassword(MD5Utils.getMD5(e.getUsername()));
employeeService.add(e);
});
if (result.isVerfiyFail()) { //验证是否失败---->失败则让用户更改后再导入
//文件下载功能:将验证失败的数据放入excel文件中,让用户下载
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-disposition", "attachment;filename=errors.xlsx");
response.setHeader("Pragma", "No-cache");
//ServletOutputStream fos = response.getOutputStream();
OutputStream fos = response.getOutputStream();
//获取验证失败的Workbook对象
result.getFailWorkbook().write(fos);
//关闭资源
fos.flush();
fos.close();
}
request.setAttribute("msgSuccess","导入成功!");
return "employee/empimport";
}
}