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

如何在返回服务端异常时保证output体不为空?

解决方案

要实现异常触发时同时返回非空output和错误信息,需要从异常携带业务数据、响应体结构支持、流程异常捕获三个方面调整代码:

1. 扩展自定义异常类,携带业务数据

修改MyException,添加字段存储需要返回的output内容,确保异常抛出时能带上已处理的业务数据:

public class MyException extends RuntimeException {
    private final Object businessData;

    // 新增构造器,传入错误信息和业务数据
    public MyException(String message, Object businessData) {
        super(message);
        this.businessData = businessData;
    }

    // getter方法,用于后续取出业务数据
    public Object getBusinessData() {
        return businessData;
    }
}

2. 调整RestResponse结构,支持同时返回output和错误信息

确保RestResponse类能同时容纳output和errorMessages,新增对应构造器:

import java.util.Collections;
import java.util.Map;

public class RestResponse<T> {
    private T output;
    private Map<String, String> errorMessages;

    // 成功场景构造器
    public RestResponse(T output) {
        this.output = output;
        this.errorMessages = Collections.emptyMap();
    }

    // 异常场景构造器:同时传入业务数据和错误信息
    public RestResponse(T output, String errorMessage) {
        this.output = output;
        this.errorMessages = Collections.singletonMap("EXCEPTION", errorMessage);
    }

    // 原错误场景构造器(保留兼容)
    public RestResponse(int errorCode, String message) {
        this.output = null;
        this.errorMessages = Collections.singletonMap("EXCEPTION", message);
    }

    // getter和setter方法
    public T getOutput() { return output; }
    public void setOutput(T output) { this.output = output; }
    public Map<String, String> getErrorMessages() { return errorMessages; }
    public void setErrorMessages(Map<String, String> errorMessages) { this.errorMessages = errorMessages; }
}

3. 修改业务处理流程,捕获异常时包装业务数据

在handle方法中,先预处理生成需要返回的output数据,调用服务时若抛出异常,则将output包装进MyException:

import reactor.util.function.Tuples;

private Mono<Object> handle(ServerRequest request) {
    String pathParam = request.pathVariable("pathParam");
    Long id = Long.parseLong(request.pathVariable("id"));
    
    return request.bodyToMono(Object.class)
            // 先构建要返回的output对象(根据实际业务逻辑生成)
            .map(body -> {
                // 示例:生成包含a、b字段的业务对象
                Map<String, String> output = new HashMap<>();
                output.put("a", "string");
                output.put("b", "string");
                // 返回业务数据和请求体的元组
                return Tuples.of(output, body);
            })
            .flatMap(tuple -> 
                service.s(tuple.getT2(), pathParam, id)
                        // 服务调用成功时,返回预处理的output
                        .thenReturn(tuple.getT1())
                        // 服务调用异常时,包装output到MyException
                        .onErrorMap(throwable -> new MyException(throwable.getMessage(), tuple.getT1()))
            );
}

4. 更新异常处理方法,构造包含output的响应

修改CommonHandler中的onConflictException方法,从MyException中取出业务数据,构造符合期望的响应体:

protected Mono<ServerResponse> onConflictException(MyException e) {
    // 从异常中取出业务数据
    Object businessData = e.getBusinessData();
    // 返回包含非空output和错误信息的响应
    return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .bodyValue(new RestResponse<>(businessData, e.getMessage()));
}

验证效果

调整完成后,当服务抛出MyException时,返回的响应体将同时包含非空的output和错误信息:

{
    "output": {
        "a":"string",
        "b":"string"
    },
    "errorMessages": {
        "EXCEPTION": "Errors string"
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:48:23