将数据导出为excel文件是项目中经常遇到的需求,用EasyExcel实现导出虽然很简单,但每次都要写一堆重复的代码,如设置response对象,新建ExcelWriter、WriteSheet,writer.finish()等,感觉很难受,于是就想定义一个注解快速实现导出功能。
常规的EasyExcel导出方式
@Service
public class EasyExcelService {
@Autowired
UserMapper userMapper;
public void download(HttpServletResponse response) throws IOException {
List<User> list = userMapper.selectUserList();
String fileName = "用户数据.xlsx";
fileName = URLEncoder.encode(fileName,"UTF-8").replaceAll("\\+","%20");
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition","attachment;filename="+fileName);
ExcelWriter writer = new ExcelWriterBuilder()
.autoCloseStream(true)
.excelType(ExcelTypeEnum.XLSX)
.file(response.getOutputStream())
.head(User.class)
.build();
WriteSheet writeSheet = new WriteSheet();
writer.write(list,writeSheet);
writer.finish();
}
}
注解实现方式
自定义一个注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelDown {
String fileName() default "";
Class template() default Object.class;
}
我这里只定义了两个属性,fileName:导出的文件名,template:导出的模板类,可以根据实际需求添加更多属性。
定义一个切面实现导出逻辑
/**
* 定义一个切面用于处理添加了@ExcelDown注解的方法
*/
@Aspect
@Component
public class ExcelDownProcessor {
@Around(value = "@annotation(com.example.spring1.annotation.ExcelDown) && @annotation(excelDown)",argNames = "joinPoint,excelDown")
public void around(ProceedingJoinPoint joinPoint, ExcelDown excelDown) throws Throwable {
//获取response对象
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletResponse response = servletRequestAttributes.getResponse();
//注解配置的导出模板
Class<?> template = excelDown.template();
//如果没有配置默认以方法返回类型List的泛型作为模板
if("Object".equals(template.getSimpleName())){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
//获取方法返回类型List的泛型
template = Class.forName(((ParameterizedTypeImpl) method.getGenericReturnType()).getActualTypeArguments()[0].getTypeName());
}
String fileName = excelDown.fileName()+".xlsx";
fileName = URLEncoder.encode(fileName,"UTF-8").replaceAll("\\+","%20");
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition","attachment;filename="+fileName);
ExcelWriter writer = new ExcelWriterBuilder()
.autoCloseStream(true)
.excelType(ExcelTypeEnum.XLSX)
.file(response.getOutputStream())
.head(template)//设置模板
.build();
List<?> list = (List<?>) joinPoint.proceed(joinPoint.getArgs());
WriteSheet writeSheet = new WriteSheet();
writer.write(list,writeSheet);
writer.finish();
}
}
使用注解导出
@Service
public class EasyExcelService {
@Autowired
UserMapper userMapper;
@ExcelDown(fileName = "用户数据")
public List<User> download(){
return userMapper.selectUserList();
}
}
使用注解导出只需查出数据,在方法上加个注解即可,非常方便。
这里只实现了一个简单版本,实际生产可以根据需求添加如:是否分页查询、导出文件是否加密、导出文件是否压缩等更多功能。