库使用

时间:2025-04-13 14:19:47

目录

依赖

实体类

Controller

Service

所用到的接口及工具类

 ExcelUtil

 ExcelListener

 DefaultExcelListener

 DefaultExcelResult

 ExcelResult

 JsonUtils

 SpringUtils

 StreamUtils

 ValidatorUtils

 SpringUtils


使用alibab中的excel库来实现excel的导入、导出

依赖

        <dependency>
            <groupId></groupId>
            <artifactId>poi</artifactId>
            <version>5.2.3</version>
        </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.3</version>
        </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId></groupId>
                    <artifactId>poi-ooxml-schemas</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

实体类

@ExcelProperty、@ExcelIgnoreUnannotated注解

import ;
import ;
import ;
import ;
import ;

import ;


@Data
@NoArgsConstructor
@ExcelIgnoreUnannotated
public class BaseProductStackImportVo extends BaseEntity {

    private static final long serialVersionUID = 4732391370534949564L;

    /**
     * 编码
     */
    @NotBlank(message = "编码不能为空")
    @ExcelProperty(value = "编码")
    private String stackNo;

    /**
     * 名称
     */
    @NotBlank(message = "名称不能为空")
    @ExcelProperty(value = "名称")
    private String stackName;

}



===================================================================================



import ;
import ;
import ;

import ;



@Data
@ExcelIgnoreUnannotated
public class BaseProductStackVo {

    /**
     * id
     */
    private int id;

    /**
     * 编码
     */
    @ExcelProperty(value = "编码")
    private String stackNo;

    /**
     * 名称
     */
    @ExcelProperty(value = "名称")
    private String stackName;

    /**
     * 创建时间
     */
    @ExcelProperty(value = "创建时间")
    private LocalDateTime createTime;

    /**
     * 创建人姓名
     */
    @ExcelProperty(value = "创建人")
    private String createName;

    /**
     * 更新时间
     */
    @ExcelProperty(value = "更新时间")
    private LocalDateTime updateTime;

    /**
     * 更新人姓名
     */
    @ExcelProperty(value = "更新人")
    private String updateName;

}

Controller

    /**
     * 导入数据
     *
     * @param file 导入文件
     */
    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
        ExcelResult<BaseProductStackImportVo> excelResult = ((), , true);
        List<BaseProductStackImportVo> volist = ();
        List<BaseProductStackEntity> list = (volist, );
        (list);
        return (());
    }



    /**
     * 导出
     */
    @PostMapping("/export")
    public void export(@Validated() BaseProductStackBo baseBo, HttpServletResponse response) {
        List<BaseProductStackVo> list = (baseBo);
        (list, "123信息", , response);
    }



    /**
     * 下载导入模版
     */
    @PostMapping("/template")
    public void template(HttpServletResponse response) {
        List<BaseProductStackImportVo> list = new ArrayList<>();
        (list, "123信息导入模板", , response);
    }

Service

    /**
     * 批量导入
     */
    void importBatch(List<BaseProductStackEntity> importData);


    /**
     * 查询全部信息
     */
    List<BaseProductStackVo> queryAll(BaseProductStackBo baseBo);


   /**
    * 批量导入
    */
    @Override
    @Transactional(rollbackFor = )
    public void importBatch(List<BaseProductStackEntity> importData) {

        List<BaseProductStackEntity> saveOrUpdateList = new ArrayList<>();

        //验证是否有重复
        List<String> duplicates = new ArrayList<>();

        (data -> {
            String duplicate = (, ());
            if ((duplicate)) {
                throw new QMSException("导入的123信息重复,请检查:" + ());
            }

            (duplicate);

            BaseProductStackEntity baseProductStackEntity = (());
            if ((baseProductStackEntity)) {
                (data, baseProductStackEntity, ().setIgnoreNullValue(true));
                (baseProductStackEntity);
            } else {
                (data);
            }
        });

        (saveOrUpdateList);
        (entity -> {
            (buildRedisKey(()), entity);
        });
    }


   /**
    * 导出
    */
    @Override
    public List<BaseProductStackVo> queryAll(BaseProductStackBo baseBo) {
        //select * from xxx
        return (baseBo);

    }


所用到的接口及工具类

 ExcelUtil

@NoArgsConstructor(access = )
public class ExcelUtil {

    /**
     * 同步导入(适用于小数据量)
     *
     * @param is 输入流
     * @return 转换后集合
     */
    public static <T> List<T> importExcel(InputStream is, Class<T> clazz) {
        return (is).head(clazz).autoCloseStream(false).sheet().doReadSync();
    }


    /**
     * 使用校验监听器 异步导入 同步返回
     *
     * @param is         输入流
     * @param clazz      对象类型
     * @param isValidate 是否 Validator 检验 默认为是
     * @return 转换后集合
     */
    public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, boolean isValidate) {
        DefaultExcelListener<T> listener = new DefaultExcelListener<>(isValidate);
        (is, clazz, listener).sheet().doRead();
        return ();
    }

    /**
     * 使用自定义监听器 异步导入 自定义返回
     *
     * @param is       输入流
     * @param clazz    对象类型
     * @param listener 自定义监听器
     * @return 转换后集合
     */
    public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) {
        (is, clazz, listener).sheet().doRead();
        return ();
    }

    /**
     * 导出excel
     *
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     * @param clazz     实体类
     * @param response  响应体
     */
    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
        try {
            resetResponse(sheetName, response);
            ServletOutputStream os = ();
            exportExcel(list, sheetName, clazz, false, os);
        } catch (IOException e) {
            throw new RuntimeException("导出Excel异常");
        }
    }

    /**
     * 导出excel
     *
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     * @param clazz     实体类
     * @param merge     是否合并单元格
     * @param response  响应体
     */
    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response) {
        try {
            resetResponse(sheetName, response);
            ServletOutputStream os = ();
            exportExcel(list, sheetName, clazz, merge, os);
        } catch (IOException e) {
            throw new RuntimeException("导出Excel异常");
        }
    }

    /**
     * 导出excel
     *
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     * @param clazz     实体类
     * @param os        输出流
     */
    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) {
        exportExcel(list, sheetName, clazz, false, os);
    }

    /**
     * 导出excel
     *
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     * @param clazz     实体类
     * @param merge     是否合并单元格
     * @param os        输出流
     */
    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os) {
        ExcelWriterSheetBuilder builder = (os, clazz)
            .autoCloseStream(false)
            // 自动适配
            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
            // 大数值自动转换 防止失真
            .registerConverter(new ExcelBigNumberConvert())
            .sheet(sheetName);
        if (merge) {
            // 合并处理器
            (new CellMergeStrategy(list, true));
        }
        (list);
    }

    /**
     * 单表多数据模板导出 模板格式为 {.属性}
     *
     * @param filename     文件名
     * @param templatePath 模板路径 resource 目录下的路径包括模板文件名
     *                     例如: excel/
     *                     重点: 模板文件必须放置到启动类对应的 resource 目录下
     * @param data         模板需要的数据
     * @param response     响应体
     */
    public static void exportTemplate(List<Object> data, String filename, String templatePath, HttpServletResponse response) {
        try {
            resetResponse(filename, response);
            ServletOutputStream os = ();
            exportTemplate(data, templatePath, os);
        } catch (IOException e) {
            throw new RuntimeException("导出Excel异常");
        }
    }

    /**
     * 单表多数据模板导出 模板格式为 {.属性}
     *
     * @param templatePath 模板路径 resource 目录下的路径包括模板文件名
     *                     例如: excel/
     *                     重点: 模板文件必须放置到启动类对应的 resource 目录下
     * @param data         模板需要的数据
     * @param os           输出流
     */
    public static void exportTemplate(List<Object> data, String templatePath, OutputStream os) {
        ClassPathResource templateResource = new ClassPathResource(templatePath);
        ExcelWriter excelWriter = (os)
            .withTemplate(())
            .autoCloseStream(false)
            // 大数值自动转换 防止失真
            .registerConverter(new ExcelBigNumberConvert())
            .build();
        WriteSheet writeSheet = ().build();
        if ((data)) {
            throw new IllegalArgumentException("数据为空");
        }
        // 单表多数据导出 模板格式为 {.属性}
        for (Object d : data) {
            (d, writeSheet);
        }
        ();
    }

    /**
     * 多表多数据模板导出 模板格式为 {key.属性}
     *
     * @param filename     文件名
     * @param templatePath 模板路径 resource 目录下的路径包括模板文件名
     *                     例如: excel/
     *                     重点: 模板文件必须放置到启动类对应的 resource 目录下
     * @param data         模板需要的数据
     * @param response     响应体
     */
    public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) {
        try {
            resetResponse(filename, response);
            ServletOutputStream os = ();
            exportTemplateMultiList(data, templatePath, os);
        } catch (IOException e) {
            throw new RuntimeException("导出Excel异常");
        }
    }

    /**
     * 多表多数据模板导出 模板格式为 {key.属性}
     *
     * @param templatePath 模板路径 resource 目录下的路径包括模板文件名
     *                     例如: excel/
     *                     重点: 模板文件必须放置到启动类对应的 resource 目录下
     * @param data         模板需要的数据
     * @param os           输出流
     */
    public static void exportTemplateMultiList(Map<String, Object> data, String templatePath, OutputStream os) {
        ClassPathResource templateResource = new ClassPathResource(templatePath);
        ExcelWriter excelWriter = (os)
            .withTemplate(())
            .autoCloseStream(false)
            // 大数值自动转换 防止失真
            .registerConverter(new ExcelBigNumberConvert())
            .build();
        WriteSheet writeSheet = ().build();
        if ((data)) {
            throw new IllegalArgumentException("数据为空");
        }
        for (<String, Object> map : ()) {
            // 设置列表后续还有数据
            FillConfig fillConfig = ().forceNewRow().build();
            if (() instanceof Collection) {
                // 多表导出必须使用 FillWrapper
                (new FillWrapper((), (Collection<?>) ()), fillConfig, writeSheet);
            } else {
                ((), writeSheet);
            }
        }
        ();
    }

    /**
     * 重置响应体
     */
    private static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException {
        String filename = encodingFilename(sheetName);
        (response, filename);
        ("application/;charset=UTF-8");
    }

    /**
     * 解析导出值 0=男,1=女,2=未知
     *
     * @param propertyValue 参数值
     * @param converterExp  翻译注解
     * @param separator     分隔符
     * @return 解析后值
     */
    public static String convertByExp(String propertyValue, String converterExp, String separator) {
        StringBuilder propertyString = new StringBuilder();
        String[] convertSource = ();
        for (String item : convertSource) {
            String[] itemArray = ("=");
            if ((propertyValue, separator)) {
                for (String value : (separator)) {
                    if (itemArray[0].equals(value)) {
                        (itemArray[1] + separator);
                        break;
                    }
                }
            } else {
                if (itemArray[0].equals(propertyValue)) {
                    return itemArray[1];
                }
            }
        }
        return ((), separator);
    }

    /**
     * 反向解析值 男=0,女=1,未知=2
     *
     * @param propertyValue 参数值
     * @param converterExp  翻译注解
     * @param separator     分隔符
     * @return 解析后值
     */
    public static String reverseByExp(String propertyValue, String converterExp, String separator) {
        StringBuilder propertyString = new StringBuilder();
        String[] convertSource = ();
        for (String item : convertSource) {
            String[] itemArray = ("=");
            if ((propertyValue, separator)) {
                for (String value : (separator)) {
                    if (itemArray[1].equals(value)) {
                        (itemArray[0] + separator);
                        break;
                    }
                }
            } else {
                if (itemArray[1].equals(propertyValue)) {
                    return itemArray[0];
                }
            }
        }
        return ((), separator);
    }

    /**
     * 编码文件名
     */
    public static String encodingFilename(String filename) {
        return () + "_" + filename + ".xlsx";
    }

}

 ExcelListener<T>

import ;

/**
 * Excel 导入监听
 *
 * @author chensir
 */
public interface ExcelListener<T> extends ReadListener<T> {

    ExcelResult<T> getExcelResult();

}

 DefaultExcelListener<T>



import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .slf4j.Slf4j;

import ;
import ;
import ;
import ;

/**
 * Excel 导入监听
 *
 * @author chensir
 */
@Slf4j
@NoArgsConstructor
public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {

    /**
     * 是否Validator检验,默认为是
     */
    private Boolean isValidate = ;

    /**
     * excel 表头数据
     */
    private Map<Integer, String> headMap;

    /**
     * 导入回执
     */
    private ExcelResult<T> excelResult;

    public DefaultExcelListener(boolean isValidate) {
         = new DefaultExcelResult<>();
         = isValidate;
    }

    /**
     * 处理异常
     *
     * @param exception ExcelDataConvertException
     * @param context   Excel 上下文
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        String errMsg = null;
        if (exception instanceof ExcelDataConvertException) {
            // 如果是某一个单元格的转换异常 能获取到具体行号
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
            Integer rowIndex = ();
            Integer columnIndex = ();
            errMsg = ("第{}行-第{}列-表头{}: 解析异常<br/>",
                rowIndex + 1, columnIndex + 1, (columnIndex));
            if (()) {
                (errMsg);
            }
        }
        if (exception instanceof ConstraintViolationException) {
            ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
            Set<ConstraintViolation<?>> constraintViolations = ();
            String constraintViolationsMsg = (constraintViolations, ConstraintViolation::getMessage, ", ");
            errMsg = ("第{}行数据校验异常: {}", ().getRowIndex() + 1, constraintViolationsMsg);
            if (()) {
                (errMsg);
            }
        }
        ().add(errMsg);
        throw new ExcelAnalysisException(errMsg);
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
         = headMap;
        ("解析到一条表头数据: {}", (headMap));
    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        if (isValidate) {
            (data);
        }
        ().add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        ("所有数据解析完成!");
    }

    @Override
    public ExcelResult<T> getExcelResult() {
        return excelResult;
    }

}

 DefaultExcelResult<T>

import ;
import ;

import ;
import ;

/**
 * 默认excel返回对象
 *
 * @author chensir
 */
public class DefaultExcelResult<T> implements ExcelResult<T> {

    /**
     * 数据对象list
     */
    @Setter
    private List<T> list;

    /**
     * 错误信息列表
     */
    @Setter
    private List<String> errorList;

    public DefaultExcelResult() {
         = new ArrayList<>();
         = new ArrayList<>();
    }

    public DefaultExcelResult(List<T> list, List<String> errorList) {
         = list;
         = errorList;
    }

    public DefaultExcelResult(ExcelResult<T> excelResult) {
         = ();
         = ();
    }

    @Override
    public List<T> getList() {
        return list;
    }

    @Override
    public List<String> getErrorList() {
        return errorList;
    }

    /**
     * 获取导入回执
     *
     * @return 导入回执
     */
    @Override
    public String getAnalysis() {
        int successCount = ();
        int errorCount = ();
        if (successCount == 0) {
            return "读取失败,未解析到数据";
        } else {
            if (errorCount == 0) {
                return ("恭喜您,全部读取成功!共{}条", successCount);
            } else {
                return "";
            }
        }
    }
}

 ExcelResult<T>

/**
 * excel返回对象
 *
 * @author chensir
 */
public interface ExcelResult<T> {

    /**
     * 对象列表
     */
    List<T> getList();

    /**
     * 错误列表
     */
    List<String> getErrorList();

    /**
     * 导入回执
     */
    String getAnalysis();
}

 JsonUtils

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;

/**
 * JSON 工具类
 *
 * @author chensir
 */
@NoArgsConstructor(access = )
public class JsonUtils {

    private static final ObjectMapper OBJECT_MAPPER = ();

    public static ObjectMapper getObjectMapper() {
        return OBJECT_MAPPER;
    }

    public static String toJsonString(Object object) {
        if ((object)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T parseObject(String text, Class<T> clazz) {
        if ((text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
        if ((bytes)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(bytes, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T parseObject(String text, TypeReference<T> typeReference) {
        if ((text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, typeReference);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static Dict parseMap(String text) {
        if ((text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType());
        } catch (MismatchedInputException e) {
            // 类型不匹配说明不是json
            return null;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static List<Dict> parseArrayMap(String text) {
        if ((text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(, ));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> List<T> parseArray(String text, Class<T> clazz) {
        if ((text)) {
            return new ArrayList<>();
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(, clazz));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

 SpringUtils

import ;
import ;
import ;
import ;
import ;

/**
 * spring工具类
 *
 * @author chensir
 */
@Component
public final class SpringUtils extends SpringUtil {

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
     * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getAliases(name);
    }

    /**
     * 获取aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        return (T) ();
    }


    /**
     * 获取spring上下文
     */
    public static ApplicationContext context() {
        return getApplicationContext();
    }

}

 StreamUtils

import ;
import ;
import ;
import ;

import .*;
import ;
import ;
import ;
import ;

/**
 * stream 流工具类
 *
 * @author chensir
 */
@NoArgsConstructor(access = )
public class StreamUtils {

    /**
     * 将collection过滤
     *
     * @param collection 需要转化的集合
     * @param function   过滤方法
     * @return 过滤后的list
     */
    public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) {
        if ((collection)) {
            return ();
        }
        return ().filter(function).collect(());
    }

    /**
     * 将collection拼接
     *
     * @param collection 需要转化的集合
     * @param function   拼接方法
     * @return 拼接后的list
     */
    public static <E> String join(Collection<E> collection, Function<E, String> function) {
        return join(collection, function, );
    }

    /**
     * 将collection拼接
     *
     * @param collection 需要转化的集合
     * @param function   拼接方法
     * @param delimiter  拼接符
     * @return 拼接后的list
     */
    public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
        if ((collection)) {
            return ;
        }
        return ().map(function).filter(Objects::nonNull).collect((delimiter));
    }

    /**
     * 将collection排序
     *
     * @param collection 需要转化的集合
     * @param comparing  排序方法
     * @return 排序后的list
     */
    public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) {
        if ((collection)) {
            return ();
        }
        return ().sorted(comparing).collect(());
    }

    /**
     * 将collection转化为类型不变的map<br>
     * <B>{@code Collection<V>  ---->  Map<K,V>}</B>
     *
     * @param collection 需要转化的集合
     * @param key        V类型转化为K类型的lambda方法
     * @param <V>        collection中的泛型
     * @param <K>        map中的key类型
     * @return 转化后的map
     */
    public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
        if ((collection)) {
            return ();
        }
        return ().collect((key, (), (l, r) -> l));
    }

    /**
     * 将Collection转化为map(value类型与collection的泛型不同)<br>
     * <B>{@code Collection<E> -----> Map<K,V>  }</B>
     *
     * @param collection 需要转化的集合
     * @param key        E类型转化为K类型的lambda方法
     * @param value      E类型转化为V类型的lambda方法
     * @param <E>        collection中的泛型
     * @param <K>        map中的key类型
     * @param <V>        map中的value类型
     * @return 转化后的map
     */
    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
        if ((collection)) {
            return ();
        }
        return ().collect((key, value, (l, r) -> l));
    }

    /**
     * 将collection按照规则(比如有相同的班级id)分类成map<br>
     * <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
     *
     * @param collection 需要分类的集合
     * @param key        分类的规则
     * @param <E>        collection中的泛型
     * @param <K>        map中的key类型
     * @return 分类后的map
     */
    public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
        if ((collection)) {
            return ();
        }
        return collection
            .stream()
            .collect((key, LinkedHashMap::new, ()));
    }

    /**
     * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
     * <B>{@code Collection<E>  --->  Map<T,Map<U,List<E>>> } </B>
     *
     * @param collection 需要分类的集合
     * @param key1       第一个分类的规则
     * @param key2       第二个分类的规则
     * @param <E>        集合元素类型
     * @param <K>        第一个map中的key类型
     * @param <U>        第二个map中的key类型
     * @return 分类后的map
     */
    public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) {
        if ((collection)) {
            return ();
        }
        return collection
            .stream()
            .collect((key1, LinkedHashMap::new, (key2, LinkedHashMap::new, ())));
    }

    /**
     * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
     * <B>{@code Collection<E>  --->  Map<T,Map<U,E>> } </B>
     *
     * @param collection 需要分类的集合
     * @param key1       第一个分类的规则
     * @param key2       第二个分类的规则
     * @param <T>        第一个map中的key类型
     * @param <U>        第二个map中的key类型
     * @param <E>        collection中的泛型
     * @return 分类后的map
     */
    public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) {
        if ((collection) || key1 == null || key2 == null) {
            return ();
        }
        return collection
            .stream()
            .collect((key1, LinkedHashMap::new, (key2, (), (l, r) -> l)));
    }

    /**
     * 将collection转化为List集合,但是两者的泛型不同<br>
     * <B>{@code Collection<E>  ------>  List<T> } </B>
     *
     * @param collection 需要转化的集合
     * @param function   collection中的泛型转化为list泛型的lambda表达式
     * @param <E>        collection中的泛型
     * @param <T>        List中的泛型
     * @return 转化后的list
     */
    public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
        if ((collection)) {
            return ();
        }
        return collection
            .stream()
            .map(function)
            .filter(Objects::nonNull)
            .collect(());
    }

    /**
     * 将collection转化为Set集合,但是两者的泛型不同<br>
     * <B>{@code Collection<E>  ------>  Set<T> } </B>
     *
     * @param collection 需要转化的集合
     * @param function   collection中的泛型转化为set泛型的lambda表达式
     * @param <E>        collection中的泛型
     * @param <T>        Set中的泛型
     * @return 转化后的Set
     */
    public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
        if ((collection) || function == null) {
            return ();
        }
        return collection
            .stream()
            .map(function)
            .filter(Objects::nonNull)
            .collect(());
    }


    /**
     * 合并两个相同key类型的map
     *
     * @param map1  第一个需要合并的 map
     * @param map2  第二个需要合并的 map
     * @param merge 合并的lambda,将key  value1 value2合并成最终的类型,注意value可能为空的情况
     * @param <K>   map中的key类型
     * @param <X>   第一个 map的value类型
     * @param <Y>   第二个 map的value类型
     * @param <V>   最终map的value类型
     * @return 合并后的map
     */
    public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) {
        if ((map1) && (map2)) {
            return ();
        } else if ((map1)) {
            map1 = ();
        } else if ((map2)) {
            map2 = ();
        }
        Set<K> key = new HashSet<>();
        (());
        (());
        Map<K, V> map = new HashMap<>();
        for (K t : key) {
            X x = (t);
            Y y = (t);
            V z = (x, y);
            if (z != null) {
                (t, z);
            }
        }
        return map;
    }

}

 ValidatorUtils

import ;
import ;
import ;

import ;
import ;
import ;
import ;

/**
 * Validator 校验框架工具
 *
 * @author chensir
 */
@NoArgsConstructor(access = )
public class ValidatorUtils {

    private static final Validator VALID = ();

    public static <T> void validate(T object, Class<?>... groups) {
        Set<ConstraintViolation<T>> validate = (object, groups);
        if (!()) {
            throw new ConstraintViolationException("参数校验异常", validate);
        }
    }

}

 SpringUtils


import ;
import ;
import ;
import ;
import ;

/**
 * spring工具类
 *
 * @author chensir
 */
@Component
public final class SpringUtils extends SpringUtil {

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
     * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getAliases(name);
    }

    /**
     * 获取aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        return (T) ();
    }


    /**
     * 获取spring上下文
     */
    public static ApplicationContext context() {
        return getApplicationContext();
    }

}

。。。。