使用CompletableFuture异步上传图片

        /**
         * 异步处理嵌套图片及后续更新
         */

        //获取当前请求上下文和租户信息,以便在线程池中复用
        /**
         * RequestContextHolder.getRequestAttributes():
         * 从当前线程的 ThreadLocal 中取出 Spring MVC 持有的 RequestAttributes,包含了 HttpServletRequest、HttpServletResponse 等信息。
         *
         * requireNonNull(...):确保获取到的上下文不为 null,否则立刻抛出 NPE,避免后续空指针。
         * getRequest():拿到底层的 HttpServletRequest 对象,以便取出当前用户等信息。
         */
        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String username = SessionUtil.getUsername(request);//从token中解析出用户名
        //完整的请求上下文,后面在线程池里要重新注入
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //多租户场景中当前使用的数据源标识,也要在线程里重新推入
        String tenantCode = DynamicDataSourceContextHolder.peek(); // 主线程中获取
        // 创建一个异步任务
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            try {
                // 设置请求上下文
                /**
                 * 将主线程中保存下来的 requestAttributes 重新绑定到当前异步线程,
                 * 让业务中依赖 RequestContextHolder 的工具(如 SessionUtil、某些 AOP)能正常工作。
                 */
                RequestContextHolder.setRequestAttributes(requestAttributes);
                /**
                 * 恢复主线程的多租户数据源标识,确保后续数据库操作都跑在正确的库/schema 上。
                 */
                DynamicDataSourceContextHolder.push(tenantCode);
                // 执行耗时操作
                Map<Integer, File> imageFileMap = new HashMap<>();
                String path = OsUtils.isWindows() ? "D:/upload/excel/" : "/opt";//拼接请求路径
                log.info("path: {}", path);
                //提取Excel中嵌入的图片
                ExcelImportImgExtractor.readXlsxEmbeddedImages(file.getInputStream(), path, imageFileMap);

                //遍历每张图片,上传并更新用户,发送消息
                for (Integer rowNum : imageFileMap.keySet()) {
                    File imageFile = imageFileMap.get(rowNum);
                    SysUserExcelImportVO excel = excelVOList.get(rowNum - 1);//VO列表从0开始,Excel行号从1开始,需要减1
                    SysUser sysUser = baseMapper.selectById(excel.getUserId());//查出对应的SysUser
                    if (sysUser == null) continue;
                    String url = "";
                    try {
                        url = uploadFile(imageFile);//上传图片
                        sysUser.setFaceImage(url);//更新用户数据
                    } catch (IOException e) {
                        log.error("{}人脸上传失败", excel.getUsername(), e);
                    }
                    sysUser.setUpdateBy(username);
                    baseMapper.updateById(sysUser); // 确保 mapper 已注入
                    //修改发送给园区各个系统的消息,构造并发送MQ消息到各个系统
                    MqParkUser mqParkUser = new MqParkUser();
                    SysUserDTO sysUserDTO = excel.getSysUserDTO();
                    sysUserDTO.setFaceImage(url);
                    mqParkUser.setType(MqEnum.MessageType.UPDATE.getType());
                    BeanUtils.copyProperties(sysUserDTO, mqParkUser);
                    mqParkUser.setRoleIds(sysUserDTO.getRole());
                    mqMessageProducer.sendParkUserMessage(DynamicDataSourceContextHolder.peek(), mqParkUser);
                }
            } catch (Exception e) {
                log.error("【异步任务异常】", e); // 主动打印日志
            } finally {
                // 清理线程局部变量,避免内存泄漏
                RequestContextHolder.resetRequestAttributes();
            }
            return null;
        }, taskExecutor);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值