我有以下实现,我试图在任何致命异常期间处理正确的资源关闭:
private def loadPrivateKey(keyPath: String) = {
def tryReadCertificate(file: File): Try[BufferedReader] = Try { new BufferedReader(new FileReader(file)) }
def tryLoadPemParser(reader: BufferedReader): Try[PEMParser] = Try { new PEMParser(reader) }
def createXXX(buffReader: BufferedReader, pemParser: PEMParser) = try {
...
} finally {
buffReader.close()
pemParser.close()
}
tryReadCertificate(new File(keyPath, "myKey.pem")) match {
case Success(buffReader) => tryLoadPemParser(buffReader) match {
case Success(pemParser) => createXXX(buffReader, pemParser)
case Failure(fail) =>
}
case Failure(fail) =>
}
}
我已经看到我的嵌套案例块是一团糟。有一个更好的方法吗?最后,我只想确保关闭BufferedReader
和PEMParser
!
答案 0 :(得分:0)
您可以使用for-comprehension来清理一些嵌套的case语句,从而重新构建您的代码:
def tryReadCertificate(file: File): Try[BufferedReader] = Try { new BufferedReader(new FileReader(file)) }
def tryLoadPemParser(reader: BufferedReader): Try[PEMParser] = Try { new PEMParser(reader) }
def createXXX(buffReader: BufferedReader, pemParser: PEMParser) = {
...
}
val certReaderTry = tryReadCertificate(new File(keyPath, "myKey.pem"))
val pemParserTry = for{
certReader <- certReaderTry
pemParser <- tryLoadPemParser(certReader)
} yield {
createXXX(certReader, pemParser)
pemParser
}
certReaderTry foreach(_.close)
pemParserTry foreach (_.close)
这样结构化,你只会在你确定已成功打开的东西上结束近距离呼叫。
更好的是,如果您的PEMParser
碰巧延伸java.io.Closeable
,意味着Try
都包裹了Closeable
个对象,那么您可以将最后两行换成像这样的一行:
(certReaderTry.toOption ++ pemParserTry.toOption) foreach (_.close)
修改强>
回应OP的评论:在第一个示例中,如果tryreadCertificate
成功,那么certReaderTry
将是Success[BufferedReader]
,因为它成功了,就在其上调用foreach
将产生BufferedReader
然后将关闭它。如果certReaderTry
是Success
,那么(通过for-comp)我们会调用tryLoadPemParser
,如果这也成功,我们可以转到createXXX
并分配{{ 1}}到tryLoadPemParser
pemParserTry
。然后,如果val
是pemParserTry
,则Success
产生foreach
并且我们可以关闭它时会发生同样的事情。根据这个例子,只要那些PEMParser
是成功的并且其他意外事件没有发生(例如在Try
中)会一直抛出异常,那么你可以保证最后关闭相关代码将完成其工作并关闭这些资源。
<强> EDIT2 强>
如果您希望createXXX
中的值来自单独的createXXX
,那么您可以执行以下操作:
Try