最佳实践:在java.net.URL中捕获失败点
JVM新手,使用Scala和Play 2.0 我正在将一个遗留应用程序转换为Play,它需要通过Authorize.net进行支付处理。通过查看java.net.URL源代码,有许多潜在的失败点。考虑到我在下面编写的接口,您将在哪里实现try/catch块?我需要相应地调整方法签名,可能会返回一个[Error,Success]来调用客户机代码最佳实践:在java.net.URL中捕获失败点,java,scala,error-handling,io,playframework-2.0,Java,Scala,Error Handling,Io,Playframework 2.0,JVM新手,使用Scala和Play 2.0 我正在将一个遗留应用程序转换为Play,它需要通过Authorize.net进行支付处理。通过查看java.net.URL源代码,有许多潜在的失败点。考虑到我在下面编写的接口,您将在哪里实现try/catch块?我需要相应地调整方法签名,可能会返回一个[Error,Success]来调用客户机代码 import java.net.{URL, URLEncoder} import java.io.{BufferedReader, DataOutputS
import java.net.{URL, URLEncoder}
import java.io.{BufferedReader, DataOutputStream, InputStreamReader}
import javax.net.ssl._
trait Authnet {
private val prodUrl = "https://secure.authorize.net/gateway/transact.dll"
private val testUrl = "https://test.authorize.net/gateway/transact.dll"
protected def authNetProcess(params: Map[String,String]) = {
val(conn, urlParams) = connect(params)
val request = new DataOutputStream( conn.getOutputStream )
request.write(urlParams.getBytes)
request.flush()
request.close()
val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
val results = response.readLine().split("\\|")
response.close()
results.toList
}
private def connect(params: Map[String,String]) = {
val urlParams = (config ++ params) map { case(k,v) =>
URLEncoder.encode(k, "UTF-8") + "=" + URLEncoder.encode(v, "UTF-8")
} mkString("&")
lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
val conn = url.openConnection
conn.setDoOutput(true)
conn.setUseCaches(false)
(conn, urlParams)
}
private val config = Map(
'x_login -> "...",
'x_tran_key -> "...",
...
)
}
编辑好的,如果连接/流进程的任何部分失败,事务将被处理,只在打开连接时捕获错误是愚蠢的。我只是将整个事务包装在一个
捕获(操作)选项
块中,并将其保留在该块中;我不太关心错误的确切原因(不管记录的是什么),因为它是暂时的,所以捕获它,让用户再试一次;如果错误仍然存在,请与我们联系
原创
好吧,好吧,考虑到目前为止的投票和缺乏评论,我能得出的唯一结论是…这里没有人知道他们在做什么!嘿,嘿,开玩笑;-)
虽然我是JVM新手,但try/catch/finally bloat正在快速变老;通过Scala类型推理的奇妙之处,我将一般的错误处理抽象为简洁的实现:捕捉(操作)选项
捕捉(操作)
除非我收到其他反馈,否则目前我只是通过捕获连接创建来弥补(我相信,在本例中,最有可能的错误情况)。以下是新的实现:
protected def authNetProcess(params: Map[String,String]) = {
connect() match {
case Some(conn) =>
val request = new DataOutputStream(conn.getOutputStream)
request.write(getUrlParams(params).getBytes)
request.flush()
request.close()
val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
val results = response.readLine().split("\\|")
response.close()
results.toList
case None => List[String]()
}
}
private def connect() = {
lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
catching ( url.openConnection ) option match {
case Some(conn) =>
conn.setDoOutput(true)
conn.setUseCaches(false)
//conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
Some(conn)
case None => None // connection failed
}
}
我认为一个更严格的方法是将所有潜在的错误条件提取到maybeWorked选项操作中,然后将它们全部封装在一个用于理解的文档中。这可能是正确的/负责任的方法…但一天中只有这么多小时,稍后将再次讨论
感谢您的反馈 坚持经验法则: 只有在必须处理异常时才能捕获它 “必须处理”没有明确的定义,但它意味着您应该抵制捕获异常的冲动,因为您可以直接抛出不同的异常 “必须处理”主要由应用程序的工作方式或其他依赖项定义 如果应用程序需要向用户显示错误,而不是异常中止,那么这是必须的 在这种情况下,捕获expetion也会添加一些有意义的处理 如果一个API需要抛出一个不同的异常,那么这是必须的,但是API的定义可能不合理 我总是质疑用另一个异常替换一个异常的附加值 将此应用于您的示例: 它是否会增加一些值来捕获authNetProcess()中connect()的异常 不!无法在connect()内部处理该异常。因此,可以将该异常留给authNetProcess的调用方。在这里,您可以根据异常的类型提供不同的处理