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

如何用不同签名方法链式调用实现基于Vavr Either的业务流程?

优雅实现基于Vavr Either的链式业务流程处理

你的核心问题是错误地直接执行了方法而非传递函数引用,同时没有正确利用flatMap(对应C#的Bind)来串联返回Either的操作。下面是符合最佳实践的实现方案:

关键优化点

  1. 用flatMap替代map串联流程:因为每个步骤返回Either<ErrorResult, T>,flatMap会自动处理错误短路(一旦返回Left,后续步骤直接跳过),这就是Java中C# Bind的等价实现。
  2. 捕获correlationId避免冗余传递:提前从Context中提取correlationId,通过lambda捕获传入各步骤,不用将其设为类字段。
  3. 聚焦核心数据:链式调用从业务输入WhateverEntityInput开始,而非整个Context,避免冗余数据传递。

修正后的完整代码

import io.vavr.control.Either;
import java.util.UUID;

public class VavrPractice {

    public static void handle(Context context) {
        UUID correlationId = context.getCorrelationId();
        
        // 链式执行流程,自动处理错误短路
        Either<ErrorResult, WhateverEntityResult> result = Either.right(context.getWhateverEntityInput())
                .flatMap(input -> validateInput(input, correlationId))
                .flatMap(validatedInput -> mapToWhateverEntity(validatedInput, correlationId))
                .flatMap(entity -> saveToDatabase(entity, correlationId))
                .flatMap(savedEntity -> mapToWhateverEntityResult(savedEntity, correlationId));

        // 统一处理最终结果:成功/失败分支
        result.fold(
                error -> logError(error),
                success -> processSuccess(success)
        );
    }

    // 验证输入:失败返回带correlationId的ErrorResult,成功返回原输入
    private static Either<ErrorResult, WhateverEntityInput> validateInput(WhateverEntityInput input, UUID correlationId) {
        if (input == null || input.getContent().isEmpty()) {
            return Either.left(new ErrorResult(correlationId, "输入内容不能为空"));
        }
        return Either.right(input);
    }

    // 映射为实体:失败返回错误,成功返回转换后的实体
    private static Either<ErrorResult, WhateverEntity> mapToWhateverEntity(WhateverEntityInput input, UUID correlationId) {
        try {
            return Either.right(new WhateverEntity(input.getContent()));
        } catch (IllegalArgumentException e) {
            return Either.left(new ErrorResult(correlationId, "实体映射失败:" + e.getMessage()));
        }
    }

    // 存储实体:生成ID后返回带ID的实体,失败返回错误
    private static Either<ErrorResult, WhateverEntity> saveToDatabase(WhateverEntity entity, UUID correlationId) {
        try {
            UUID generatedId = UUID.randomUUID(); // 模拟存储生成ID
            entity.setId(generatedId);
            // 执行数据库存储操作
            return Either.right(entity);
        } catch (Exception e) {
            return Either.left(new ErrorResult(correlationId, "存储失败:" + e.getMessage()));
        }
    }

    // 映射为结果:将带ID的实体转换为输出结果
    private static Either<ErrorResult, WhateverEntityResult> mapToWhateverEntityResult(WhateverEntity entity, UUID correlationId) {
        try {
            return Either.right(new WhateverEntityResult(entity.getId(), entity.getContent()));
        } catch (Exception e) {
            return Either.left(new ErrorResult(correlationId, "结果映射失败:" + e.getMessage()));
        }
    }

    // 错误处理逻辑
    private static void logError(ErrorResult error) {
        System.err.printf("[Correlation ID: %s] 流程失败:%s%n", error.getCorrelationId(), error.getMessage());
    }

    // 成功处理逻辑
    private static void processSuccess(WhateverEntityResult result) {
        System.out.printf("流程完成,生成实体ID:%s%n", result.getEntityId());
    }

    // 辅助实体类定义
    static class Context {
        private WhateverEntityInput whateverEntityInput;
        private UUID correlationId;

        // 构造器、getter省略
        public WhateverEntityInput getWhateverEntityInput() { return whateverEntityInput; }
        public UUID getCorrelationId() { return correlationId; }
    }

    static class WhateverEntityInput {
        private String content;

        // 构造器、getter省略
        public String getContent() { return content; }
    }

    static class WhateverEntity {
        private UUID id;
        private String content;

        public WhateverEntity(String content) { this.content = content; }
        // setter、getter省略
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        public String getContent() { return content; }
    }

    static class WhateverEntityResult {
        private UUID entityId;
        private String content;

        public WhateverEntityResult(UUID entityId, String content) {
            this.entityId = entityId;
            this.content = content;
        }
        // getter省略
        public UUID getEntityId() { return entityId; }
    }

    static class ErrorResult {
        private UUID correlationId;
        private String message;

        public ErrorResult(UUID correlationId, String message) {
            this.correlationId = correlationId;
            this.message = message;
        }
        // getter省略
        public UUID getCorrelationId() { return correlationId; }
        public String getMessage() { return message; }
    }
}

核心逻辑说明

  • flatMap的作用:每个步骤返回Either,flatMap会自动解包Right值传递给下一个步骤;如果某个步骤返回Left,后续链式调用会直接短路,不会执行,错误信息会被保留到最终的Either中。
  • lambda捕获correlationId:提前从Context提取correlationId,在每个步骤的lambda中直接引用,既保持方法无状态,又避免重复从Context取值。
  • 结果处理:用fold方法统一处理成功(Right分支)和失败(Left分支),这是Vavr处理Either结果的标准方式。

内容的提问来源于stack exchange,提问作者AndrasCsanyi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:40:55