栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

文件异步导入及springboot MultipartFile 上传文件后@Async异步处理报错:NoSuchFileException

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

文件异步导入及springboot MultipartFile 上传文件后@Async异步处理报错:NoSuchFileException

第一个问题

当excel中的数据量比较大时,java后台解析的过程可能要持续很久,但是又不需要用户去进行等待,这时就考虑文件的异步导入

文件异步方法的实现有着几种实现方式,这里是通过指定异步线程池实现的,即@Async(“线程池名称”)标注异步方法。

然而,在经过测试时发现,该标注的注解也都标注了,但是就是不能实现异步效果。

几经波折,发现异步方法可以调用非异步方法,是可以实现异步效果;而先是非异步方法去调用异步方法,这样就会失效。这里所说的是在同一个java类里面。

而在不同的java类里面,就不存在上面的问题

第二个问题
使用了异步方法,通过controller接收文件,service层进行处理,这时controller已经将执行成功的结果返回,剩下的就是service层中去进行解析入库,结果,万万没想到,在service中报了一个错

java.nio.file.NoSuchFileException: D:UserDataTempundertow.1407321862395783323.8400undertow4517937229384702645upload

Controller中的方法

@PostMapping("/test")
public R test(MultipartFile file) {
	testService.test(file);
	return R.success("导入成功");
}

Service中的方法

@Async("asyncimportExecutor")
public void test(MultipartFile file) {
    try {
        EasyExcelUtil.read(file.getInputStream(), Test.class, this::executeimport)
                    .sheet().doRead();
    } catch (Exception ex) {
        log.error("[test]异步导入异常:", ex);
    }
}

看到这个异常NoSuchFileException后就一脸懵逼,测试是通过postman进行的,就开始怀疑postman的问题,已经排查后postman、路径啥的都没有问题,异步调用的流程也是ok的

然后就想这个异常的提示,就是找不到文件,根据打印出来的日志去本地也确实没有找到。后来就有了下面的写法

Controller中的方法

@PostMapping("/test")
public R test(MultipartFile file) {
	try {
		testService.test(file.getInputStream());
	} catch (IOException e) {
		log.error("[test]异常日志:", e);
		return R.fail("导入失败");
	}
	return R.success("导入成功");
}

Service中的方法

@Async("asyncimportExecutor")
public void test(InputStream file) {
    try {
        EasyExcelUtil.read(file, Test.class, this::executeimport)
                    .sheet().doRead();
    } catch (Exception ex) {
        log.error("[test]异步导入异常:", ex);
    }
}

这样就不报错了。。。
后来就进行debug调试,发现临时文件是controller层中的MultipartFile对象生成,一直在写同步方法,也没注意这个MultipartFile对象会生成临时文件。后来发现这个controller中返回结果后,临时文件也就没有了。

错误总结:
因为使用的是异步方法,这样就会有一个主线程和一个异步线程。在上传文件后会形成MultipartFile类型的实例,同时生成临时文件,此时是在主线程中。MultipartFile的实例交给异步线程处理后,该临时文件会被springboot(spring)销毁,在异步线程中去getInputStream就会出现上面的异常。

而在下面的写法是将InputStream流作为了入参,就不会产生找不到文件的情况。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/329023.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号