在 Kotlin 中使用 HTTP 客户端时如何正确处理错误?
How to handle errors properly when using HTTP client in Kotlin?
我有以下代码,它使用 Apache HTTP 客户端联系外部系统 (Capsule CRM)。
override fun findPartiesByUrlFragment(urlFragment: String): PartiesSearchResult {
val req = HttpGet("https://api.capsulecrm.com/api/v2/parties/search?q=${urlFragment}")
req.setHeader("Authorization", "Bearer ${ApiToken}")
req.setHeader("Accept", "application/json");
val httpClient = HttpClients.createDefault()
val res = httpClient.execute(req)
val parser = Parser()
val json:JsonObject = parser.parse(res.entity.content) as JsonObject
[...] // What happens thereafter isn't relevant because most errors are likely to occur in the code above
return PartiesSearchResult(false, "", emptyList())
}
这段代码必须在 24/7 全天候运行的应用程序中工作,因此我需要进行正确的错误处理并确保整个应用程序不会崩溃,如果出现预期的问题(例如 Capsule 的服务器已关闭) )发生。 PartiesSearchResult(false, "", emptyList())
中的false
表示操作失败。
我可以检查 HTTP 响应代码并仅解析响应,如果它是 200。
但我很困惑,因为我在这里没有看到任何声明的异常(与 Java 相反)。
现在我想这样做:
override fun findPartiesByUrlFragment(urlFragment: String): PartiesSearchResult {
var httpClient = null
var res = null
try {
val req = HttpGet("https://api.capsulecrm.com/api/v2/parties/search?q=${urlFragment}")
req.setHeader("Authorization", "Bearer ${ApiToken}")
req.setHeader("Accept", "application/json");
httpClient = HttpClients.createDefault()
res = httpClient.execute(req)
if (res == null) {
return PartiesSearchResult(false, "null response", emptyList())
}
if (res.entity == null) {
return PartiesSearchResult(false, "null entity", emptyList())
}
val content = res.entity.content
if (content == null) {
return PartiesSearchResult(false, "null content", emptyList())
}
if (responseCode(res) == 200) {
val parser = Parser()
val json:JsonObject = parser.parse(content) as JsonObject
[...] // Convert JSON to my own objects
return PartiesSearchResult(true, "", emptyList())
}
return PartiesSearchResult(false, "Invalid HTTP response code", emptyList())
}
catch (Throwable t) {
return PartiesSearchResult(false, toString(t), emptyList())
}
finally {
closeIfNotNull(res)
closeIfNotNull(httpClient)
}
return PartiesSearchResult(false, "", emptyList())
}
如果我的系统不能因为预期的问题情况(外部服务器宕机、外部服务器过载或有内部错误、互联网连接暂时丢失等)?
您有多种选择可以更好地维护此方法。这些选项不一定特定于 Kotlin。更像是 Refactoring and Object design。最明显的一种是将其拆分为多种方法。由于您的方法处理多个不同的问题,您可以将其拆分为更有针对性的部分。然后彻底 test, errorproof 和 log 他们的行为。
例如:
- 第一部分处理 HTTP GET 请求。将其提取到返回 GET 响应的方法并检查 connection exceptions.
- 可以提取中间部分作为 GET 响应的验证,以确保您获得了有效的数据。
- 最后一部分再次关注从 GET 响应中解析 JSON。处理解析器异常的地方。
我有以下代码,它使用 Apache HTTP 客户端联系外部系统 (Capsule CRM)。
override fun findPartiesByUrlFragment(urlFragment: String): PartiesSearchResult {
val req = HttpGet("https://api.capsulecrm.com/api/v2/parties/search?q=${urlFragment}")
req.setHeader("Authorization", "Bearer ${ApiToken}")
req.setHeader("Accept", "application/json");
val httpClient = HttpClients.createDefault()
val res = httpClient.execute(req)
val parser = Parser()
val json:JsonObject = parser.parse(res.entity.content) as JsonObject
[...] // What happens thereafter isn't relevant because most errors are likely to occur in the code above
return PartiesSearchResult(false, "", emptyList())
}
这段代码必须在 24/7 全天候运行的应用程序中工作,因此我需要进行正确的错误处理并确保整个应用程序不会崩溃,如果出现预期的问题(例如 Capsule 的服务器已关闭) )发生。 PartiesSearchResult(false, "", emptyList())
中的false
表示操作失败。
我可以检查 HTTP 响应代码并仅解析响应,如果它是 200。
但我很困惑,因为我在这里没有看到任何声明的异常(与 Java 相反)。
现在我想这样做:
override fun findPartiesByUrlFragment(urlFragment: String): PartiesSearchResult {
var httpClient = null
var res = null
try {
val req = HttpGet("https://api.capsulecrm.com/api/v2/parties/search?q=${urlFragment}")
req.setHeader("Authorization", "Bearer ${ApiToken}")
req.setHeader("Accept", "application/json");
httpClient = HttpClients.createDefault()
res = httpClient.execute(req)
if (res == null) {
return PartiesSearchResult(false, "null response", emptyList())
}
if (res.entity == null) {
return PartiesSearchResult(false, "null entity", emptyList())
}
val content = res.entity.content
if (content == null) {
return PartiesSearchResult(false, "null content", emptyList())
}
if (responseCode(res) == 200) {
val parser = Parser()
val json:JsonObject = parser.parse(content) as JsonObject
[...] // Convert JSON to my own objects
return PartiesSearchResult(true, "", emptyList())
}
return PartiesSearchResult(false, "Invalid HTTP response code", emptyList())
}
catch (Throwable t) {
return PartiesSearchResult(false, toString(t), emptyList())
}
finally {
closeIfNotNull(res)
closeIfNotNull(httpClient)
}
return PartiesSearchResult(false, "", emptyList())
}
如果我的系统不能因为预期的问题情况(外部服务器宕机、外部服务器过载或有内部错误、互联网连接暂时丢失等)?
您有多种选择可以更好地维护此方法。这些选项不一定特定于 Kotlin。更像是 Refactoring and Object design。最明显的一种是将其拆分为多种方法。由于您的方法处理多个不同的问题,您可以将其拆分为更有针对性的部分。然后彻底 test, errorproof 和 log 他们的行为。
例如:
- 第一部分处理 HTTP GET 请求。将其提取到返回 GET 响应的方法并检查 connection exceptions.
- 可以提取中间部分作为 GET 响应的验证,以确保您获得了有效的数据。
- 最后一部分再次关注从 GET 响应中解析 JSON。处理解析器异常的地方。