【问题标题】:Sonar Error: Use try-with-resources or close this "ZipOutputStream" in a "finally" clause声纳错误:使用 try-with-resources 或在“finally”子句中关闭此“ZipOutputStream”
【发布时间】:2021-12-14 16:17:25
【问题描述】:

我使用 Java 在 Spring Boot 应用程序中实现了 zip 下载方法。我尝试了几种不同的解决方案,但仍然收到:使用 try-with-resources 或在来自 Sonar 的“finally”子句错误中关闭此“ZipOutputStream”

在这里你可以找到我在服务中的实现。如果你能指导我解决这个问题,我会很高兴!

@Override
public void downloadZipBySeasonId(int seasonId, HttpServletResponse response) throws IOException {
.
.
.
    if(!items.isEmpty()) {
        ZipOutputStream zipOut = null;
        try {
            zipOut = new ZipOutputStream(response.getOutputStream());  // Sonar points this line!
            for (int i = 1; i <= items.size(); i++) {
                LetterEntity letter = items.get(i - 1);
                ZipEntry zipEntry = new ZipEntry(letter.getLetterName());
                zipOut.putNextEntry(zipEntry);
                StreamUtils.copy(letter.getLetterContent(), zipOut);
                zipOut.closeEntry();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Could not zip succesfully!");
        }
        finally {
            if(zipOut != null) {
                zipOut.finish();
                zipOut.close();
            }
        }
        response.setStatus(HttpServletResponse.SC_OK);
        response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + zipFileName + "\"");
    } else {
        response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }
}

【问题讨论】:

  • 你知道为什么 try-with-resources 是个好主意吗?

标签: java spring spring-boot sonarqube sonarqube-scan


【解决方案1】:

尝试使用 ressources 自动关闭 ressources(像 Streams , Buffereds ..这样的资源) 你不需要关闭 finally 块中的读取器或写入器,你不需要编写 finally 块,也可以避免编写 catch 块..

例子

 try (BufferedReader r = Files.newBufferedReader(path1);
  BufferedWriter w = Files.newBufferedWriter(path2))
 {
  //protected code
 }
 catch (Exception e) {
  // exeption handler
 } 

文档:https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

【讨论】:

  • 非常感谢!它有助于解决问题!
【解决方案2】:

将资源尝试应用于初始代码如下所示。在这里,您不必在 finally 块中关闭流。退出 try catch 块时它会关闭。由于空检查,存在声纳问题。

 if(!items.isEmpty()) {
        
        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());){
            for (int i = 1; i <= items.size(); i++) {
                LetterEntity letter = items.get(i - 1);
                ZipEntry zipEntry = new ZipEntry(letter.getLetterName());
                zipOut.putNextEntry(zipEntry);
                StreamUtils.copy(letter.getLetterContent(), zipOut);
                zipOut.closeEntry();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Could not zip succesfully!");
        }

        response.setStatus(HttpServletResponse.SC_OK);
        response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + zipFileName + "\"");
    } else {
        response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }

【讨论】:

  • 解决了问题!非常感谢!
【解决方案3】:

Try with resources 是一个非常漂亮的概念,它消除了在 finally 块中关闭资源的痛苦,这也是你编写的几行额外代码。 Try with resources 会自动关闭资源,使您的代码简洁并在任何情况下都可以关闭资源。

语法:

    Scanner scanner = null;
try {
    scanner = new Scanner(new File("scan.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}

尝试资源:

    try (Scanner scanner = new Scanner(new File("scan.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

【讨论】:

  • 非常感谢!它有助于解决问题!
猜你喜欢
  • 2019-07-08
  • 2021-10-08
  • 1970-01-01
  • 2019-03-31
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
相关资源
最近更新 更多