You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:04:52