使用VAVR(原javaslang)时如何记录异常?
在VAVR(原Javaslang)中优雅记录HTTP请求异常
看起来你想在使用VAVR处理HTTP请求时,优雅地捕获并记录异常——刚好我有几个实用的方案,结合你给出的代码片段来整理一下:
核心思路
我们要利用VAVR的Try类型包裹所有可能抛出异常的HTTP操作(请求、响应解析),再通过fold方法统一处理成功/失败分支,同时结合RxJava的Observable维持流的连续性。
优化后的完整代码
import io.reactivex.Observable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javaslang.control.Try; import org.apache.http.HttpResponse; import org.apache.http.util.EntityUtils; import java.util.List; public class HttpProcessingService { private static final Logger LOGGER = LoggerFactory.getLogger(HttpProcessingService.class); public Observable<String> fetchAndProcessData() { String sampleUrl = "http://someurl.com"; // 会返回500的测试URL List<String> myList = List.of(sampleUrl); LOGGER.info("In {} with urls {}", getClass().getSimpleName(), myList); return Observable.from(myList) .flatMap(url -> Observable.create(subscriber -> { // 用Try包裹完整的HTTP请求+解析流程 Try<String> httpResult = Try.of(() -> HttpUtil.retrieveData(url)) .flatMap(httpResponse -> validateAndParseResponse(httpResponse)); // 用fold处理Try的成功/失败分支 httpResult.fold( // 失败分支:记录日志,按需通知订阅者 error -> { LOGGER.error("Failed to process URL: {}", url, error); // 可选:如果不想中断整个流,用subscriber.onComplete()代替onError subscriber.onError(error); }, // 成功分支:发射数据并完成当前Observable data -> { subscriber.onNext(data); subscriber.onComplete(); } ); })); } // 抽离响应验证和解析逻辑,让代码更清晰 private Try<String> validateAndParseResponse(HttpResponse httpResponse) { int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode >= 400) { return Try.failure(new RuntimeException(String.format( "HTTP request failed with status: %d - %s", statusCode, httpResponse.getStatusLine().getReasonPhrase() ))); } return Try.of(() -> EntityUtils.toString(httpResponse.getEntity())); } }
关键细节说明
- 完整流程包裹:把
HttpUtil.retrieveData()和响应解析逻辑都放在Try中,不管是网络异常还是解析异常,都会被自动捕获到失败分支。 - 主动处理非2xx响应:即使HttpUtil没有抛出异常(比如仅返回500状态码),我们也主动验证状态码并转为
Try.failure,确保所有异常场景都能被统一处理。 - 灵活的流控制:在失败分支里,你可以选择调用
subscriber.onError()中断整个流,或者用subscriber.onComplete()跳过当前错误、继续处理下一个URL——完全取决于业务需求。 - 清晰的日志:日志包含具体URL和完整异常栈轨迹,方便后续排查问题。
更简洁的RxJava风格写法
如果你偏好RxJava的链式调用风格,也可以把Try和Observable结合得更紧密:
return Observable.from(myList) .flatMap(url -> Observable.fromCallable(() -> Try.of(() -> HttpUtil.retrieveData(url)) .flatMap(this::validateAndParseResponse) )) .flatMap(result -> result.fold( error -> { LOGGER.error("Failed to process URL: {}", url, error); // 返回empty则继续处理下一个元素,返回error则中断流 return Observable.empty(); }, data -> Observable.just(data) ));
这种写法用Observable.fromCallable()执行Try逻辑,再通过flatMap直接处理Try结果,代码更紧凑。
内容的提问来源于stack exchange,提问作者Jai
相关产品推荐
相关产品推荐

