前言
项目在做二手市场,然后商品的提交我们希望对商品的描述和商品的照片能一起传递到同一个接口来统一处理,而不是分发到两个接口中去处理,因为如果分到两个接口那么会特别麻烦。
文件多线程兼多文件上传
@RequestParam和@RequestPart的区别
可以先看上面这张图片展示出来的接口,我是用的是form-data表单提交,并且我并没有设定secHandGoods这个字段为application/json提交,那么默认他就是以字符串提交过去的,也就是说这里Java代码我只能使用@RequestParam的方式,如下
然后使用JSON.parseObject来完成对象类型的转换。
而如果我是用的是Postman进行请求提交,那么由于postman可以设定form-data提交的时候的content-type,那么我就可以使用@RequestPart来完成提交,如下
而postman这边设定secHandGoods这个参数为application/json即可
具体的需求对接其实是要看前端的,我们更倾向与使用第二种,因为如果使用JSON.parseObject,他的性能损耗还是有的。
大概的代码如下:
代码还没有优化,都是随便写写的,能大概跑完就行哈哈哈哈
/** * 用户更新自己的闲置商品 * * @param sechandGoods * @return */ @PutMapping("/updateGoods") public BaseResponse updateGoods( @RequestPart("files") MultipartFile[] files, //@RequestParam("secHandGoods") String jsonStr, @RequestPart("secHandGoods") SechandGoods sechandGoods, HttpServletRequest request) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException { //SechandGoods sechandGoods = JSON.parseObject(jsonStr, SechandGoods.class); WXSessionModel user = (WXSessionModel) request.getSession().getAttribute("user"); sechandGoods.setUserId(Long.valueOf(user.getUserId())); minioSysFileService.deleteFiles(sechandGoods.getGoodsPhotos()); //MultipartFile[] files = sechandGoods.getFiles(); CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); CountDownLatch countDownLatch = new CountDownLatch(files.length); for (int i = 0; i < files.length; i++) { try { MultipartFile file = files[i]; //TODO 使用CountDownLaunch或者ComplatableFuture或者Semaphore //来完成多线程的文件上传 fileThreadPool.submit(() -> { try { String url = minioSysFileService.uploadFile(file); list.add(url); } catch (Exception e) { throw new RuntimeException(e); } finally { //表示一个文件已经被完成 countDownLatch.countDown(); } }); } catch (Exception e) { throw new RuntimeException(e); } } try { //阻塞直到所有的文件完成复制 countDownLatch.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } //统计每个文件的url String photoUrls = String.join(",", list); sechandGoods.setGoodsPhotos(photoUrls); int isUpdate = sechandGoodsService.updateSechandGoods(sechandGoods); //if (isUpdate == 0) { // return ResponseData.error(CodeEnum.BODY_NOT_MATCH); //} return ResponseData.success(sechandGoods); } @Autowired private MinioSysFileServiceImpl minioSysFileService; @Autowired @Qualifier("fileThreadPool") private ThreadPoolExecutor fileThreadPool; /** * 用户上传商品 * * @param sechandGoods * @param request * @return */ @PostMapping("/saveGoods") public BaseResponse saveGoodByUserId( @RequestPart("files") MultipartFile[] files, //@RequestParam("secHandGoods") String jsonStr, @RequestPart("secHandGoods") SechandGoods sechandGoods, HttpServletRequest request) { WXSessionModel user = (WXSessionModel) request.getSession().getAttribute("user"); //SechandGoods sechandGoods = JSON.parseObject(jsonStr, SechandGoods.class); sechandGoods.setUserId(Long.valueOf(user.getUserId())); //MultipartFile[] files = sechandGoods.getFiles(); CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); CountDownLatch countDownLatch = new CountDownLatch(files.length); for (int i = 0; i < files.length; i++) { try { MultipartFile file = files[i]; //TODO 使用CountDownLaunch或者ComplatableFuture或者Semaphore //来完成多线程的文件上传 fileThreadPool.submit(() -> { try { String url = minioSysFileService.uploadFile(file); list.add(url); } catch (Exception e) { throw new RuntimeException(e); } finally { //表示一个文件已经被完成 countDownLatch.countDown(); } }); } catch (Exception e) { throw new RuntimeException(e); } } try { //阻塞直到所有的文件完成复制 countDownLatch.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } //统计每个文件的url String photoUrls = String.join(",", list); sechandGoods.setGoodsPhotos(photoUrls); sechandGoodsService.insertSechandGoods(sechandGoods); return ResponseData.success(sechandGoods); }