Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<User>
Type genericParameterType = returnType.getGenericParameterType();

// 提取实际类型参数:User.class
return (Class<?>) ((ParameterizedType) genericParameterType).getActualTypeArguments()[0];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class MvcConfiguration implements InitializingBean {

@Override
public void afterPropertiesSet() throws Exception {
// 注册自定义返回值处理器
List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
if (returnValueHandlers != null) {
List<HandlerMethodReturnValueHandler> newList = new ArrayList<>(returnValueHandlers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class UploadConfiguration implements WebMvcConfigurer {

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// 注册自定义参数解析器
resolvers.add(new UploadDataHandlerMethodArgumentResolver());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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> -> User.class)
Class<?> excelType = findExcelType(parameter);
// 5 使用 EasyExcel 解析文件
return EasyExcel.read(file.getInputStream(), excelType, null)
.sheet() // 读取第一个 sheet
.doReadSync(); // 同步读取,返回 List<User>
}
return null;
}

private Class<?> findExcelType(MethodParameter parameter) {
// 获取泛型参数类型:List<User>
Type genericParameterType = parameter.getGenericParameterType();

// 提取实际类型参数:User.class
return (Class<?>) ((ParameterizedType) genericParameterType).getActualTypeArguments()[0];
}

Expand Down
12 changes: 10 additions & 2 deletions src/main/java/tech/insight/ssexcel/controller/ExcelController.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,22 @@
@RequestMapping("/excel")
public class ExcelController {

// 导出数据 下载excel

/**
* 提供用户数据Excel文件下载接口。
* 该接口通过{@link SSExcel}注解将返回的用户列表自动转换为Excel文件,
* 文件名格式为"用户数据"后接当前日期(如"用户数据20231015")。
*/
@GetMapping("/download")
@SSExcel(excelName = "用户数据$date")
public List<User> download() {
return data();
}

/**
* 提供用户数据Excel文件上传接口
* UploadExcel注解标记该方法处理Excel上传
* ExcelData注解标记参数化接受解析后的数据
*/
@PostMapping("upload")
@UploadExcel
public String upload(@ExcelData List<User> objects) {
Expand Down