diff --git a/src/main/java/tech/insight/ssexcel/config/ExcelReturnValueHandler.java b/src/main/java/tech/insight/ssexcel/config/ExcelReturnValueHandler.java index e7406af..c70d2bb 100644 --- a/src/main/java/tech/insight/ssexcel/config/ExcelReturnValueHandler.java +++ b/src/main/java/tech/insight/ssexcel/config/ExcelReturnValueHandler.java @@ -17,33 +17,71 @@ **/ public class ExcelReturnValueHandler implements HandlerMethodReturnValueHandler { + /** + * 判断是否支持指定的返回值类型 + */ @Override public boolean supportsReturnType(MethodParameter returnType) { + // 检查条件: + // 1. 方法有 @SSExcel 注解 + // 2. 返回值类型是 Collection 的子类(如 List) return returnType.hasMethodAnnotation(SSExcel.class) && Collection.class.isAssignableFrom(returnType.getParameterType()); } + + /** + * 处理返回值并将其转换为Excel文件进行下载 + */ @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { + // 1 获取注解信息 SSExcel ssExcel = returnType.getMethodAnnotation(SSExcel.class); + + // 2 设置 HTTP 响应头 HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); - String template = ssExcel.excelName(); - String excelName = analysisExcelName(template); + + // 3 处理文件名 + String template = ssExcel.excelName(); // "用户数据$date" + String excelName = analysisExcelName(template); // "用户数据1703123456789" String fileName = URLEncoder.encode(excelName, "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - Class excelType = findExcelType(returnType); - EasyExcel.write(response.getOutputStream(), excelType).sheet("模板").doWrite((Collection) returnValue); + + // 4 解析数据类型 + Class excelType = findExcelType(returnType); // User.class + + // 5 使用 EasyExcel 生成文件 + EasyExcel.write(response.getOutputStream(), excelType) + .sheet("模板") // 设置 sheet 名称 + .doWrite((Collection) returnValue); // 写入数据 } + + /** + * 解析Excel文件名模板,将模板中的$date占位符替换为当前时间戳 + * + * @param template Excel文件名模板字符串,其中可能包含$date占位符 + * @return 替换后的Excel文件名,其中$date被替换为当前时间戳 + */ private String analysisExcelName(String template) { + // 将模板中的$date占位符替换为当前系统时间戳 return template.replace("$date", System.currentTimeMillis() + ""); } + /** + * 查找Excel数据的泛型类型 + * + * @param returnType 方法参数对象,用于获取泛型类型信息 + * @return 返回Excel数据的泛型类型Class对象 + */ private Class findExcelType(MethodParameter returnType) { + // 获取泛型参数类型:List Type genericParameterType = returnType.getGenericParameterType(); + + // 提取实际类型参数:User.class return (Class) ((ParameterizedType) genericParameterType).getActualTypeArguments()[0]; } diff --git a/src/main/java/tech/insight/ssexcel/config/MvcConfiguration.java b/src/main/java/tech/insight/ssexcel/config/MvcConfiguration.java index d84d8fc..d9d20e8 100644 --- a/src/main/java/tech/insight/ssexcel/config/MvcConfiguration.java +++ b/src/main/java/tech/insight/ssexcel/config/MvcConfiguration.java @@ -22,6 +22,7 @@ public class MvcConfiguration implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { + // 注册自定义返回值处理器 List returnValueHandlers = adapter.getReturnValueHandlers(); if (returnValueHandlers != null) { List newList = new ArrayList<>(returnValueHandlers); diff --git a/src/main/java/tech/insight/ssexcel/config/UploadConfiguration.java b/src/main/java/tech/insight/ssexcel/config/UploadConfiguration.java index e0791b4..f84aaec 100644 --- a/src/main/java/tech/insight/ssexcel/config/UploadConfiguration.java +++ b/src/main/java/tech/insight/ssexcel/config/UploadConfiguration.java @@ -14,6 +14,7 @@ public class UploadConfiguration implements WebMvcConfigurer { @Override public void addArgumentResolvers(List resolvers) { + // 注册自定义参数解析器 resolvers.add(new UploadDataHandlerMethodArgumentResolver()); } } diff --git a/src/main/java/tech/insight/ssexcel/config/UploadDataHandlerMethodArgumentResolver.java b/src/main/java/tech/insight/ssexcel/config/UploadDataHandlerMethodArgumentResolver.java index 0a3a77f..186676a 100644 --- a/src/main/java/tech/insight/ssexcel/config/UploadDataHandlerMethodArgumentResolver.java +++ b/src/main/java/tech/insight/ssexcel/config/UploadDataHandlerMethodArgumentResolver.java @@ -20,22 +20,36 @@ public class UploadDataHandlerMethodArgumentResolver implements HandlerMethodArg @Override public boolean supportsParameter(MethodParameter parameter) { + // 检查条件: + // 1. 参数有 @ExcelData 注解 + // 2. 方法有 @UploadExcel 注解 return parameter.hasParameterAnnotation(ExcelData.class) && parameter.hasMethodAnnotation(UploadExcel.class); } @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + // 1 获取 HTTP 请求 HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + + // 2 检查是否为文件上传请求 if (request instanceof MultipartRequest multipartRequest) { + // 3 获取上传的文件(参数名为 "file") MultipartFile file = multipartRequest.getFile("file"); - return EasyExcel.read(file.getInputStream(), findExcelType(parameter), null).sheet().doReadSync(); + // 4 解析泛型类型(List -> User.class) + Class excelType = findExcelType(parameter); + // 5 使用 EasyExcel 解析文件 + return EasyExcel.read(file.getInputStream(), excelType, null) + .sheet() // 读取第一个 sheet + .doReadSync(); // 同步读取,返回 List } return null; } private Class findExcelType(MethodParameter parameter) { + // 获取泛型参数类型:List Type genericParameterType = parameter.getGenericParameterType(); + + // 提取实际类型参数:User.class return (Class) ((ParameterizedType) genericParameterType).getActualTypeArguments()[0]; } diff --git a/src/main/java/tech/insight/ssexcel/controller/ExcelController.java b/src/main/java/tech/insight/ssexcel/controller/ExcelController.java index f0b8f38..26f207d 100644 --- a/src/main/java/tech/insight/ssexcel/controller/ExcelController.java +++ b/src/main/java/tech/insight/ssexcel/controller/ExcelController.java @@ -20,14 +20,22 @@ @RequestMapping("/excel") public class ExcelController { - // 导出数据 下载excel - + /** + * 提供用户数据Excel文件下载接口。 + * 该接口通过{@link SSExcel}注解将返回的用户列表自动转换为Excel文件, + * 文件名格式为"用户数据"后接当前日期(如"用户数据20231015")。 + */ @GetMapping("/download") @SSExcel(excelName = "用户数据$date") public List download() { return data(); } + /** + * 提供用户数据Excel文件上传接口 + * UploadExcel注解标记该方法处理Excel上传 + * ExcelData注解标记参数化接受解析后的数据 + */ @PostMapping("upload") @UploadExcel public String upload(@ExcelData List objects) {