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

第三方API响应码处理最佳实践:以天气API对接场景为例

最优方案与代码组织

这个场景下自定义异常+全局异常映射是最优的组织方式,也是业内对接第三方API的通用实践,比返回带状态的实体更合理,核心优势是业务逻辑与错误处理完全解耦,代码可读性和可扩展性更高。

你当前用的是JAX-RS标准的接口定义(@Path、Response),这套方案完美适配现有技术栈,不需要大改原有代码:

  1. 先定义一组自定义异常,对应不同的错误场景,也可以封装一个通用父异常承载HTTP状态码,减少重复代码
  2. 在weatherService对接第三方API的逻辑中,解析第三方返回的状态码,错误场景直接抛出对应的自定义异常
  3. 用JAX-RS的ExceptionMapper或者Spring生态的@RestControllerAdvice做全局异常统一处理,直接转换成对应状态码的响应

两种方案对比

自定义异常(推荐)

  • 适用场景:当前这种第三方调用错误属于非预期的异常分支,符合Java异常机制的设计初衷
  • 优势:业务接口代码完全不需要加错误判断的if-else,错误处理逻辑统一收口,后续要加错误日志、监控告警只需要在异常处理器里修改即可,不需要侵入业务代码
  • 符合防腐层(Anticorruption Layer)的设计思想,把第三方API的错误模型和你的系统逻辑完全隔离开,避免第三方的接口定义渗透到上层业务

带状态的返回实体

  • 适用场景:如果错误属于业务正常流程的一部分(比如用户操作类的业务错误,需要前端做特殊跳转/提示),可以用返回实体承载状态
  • 劣势:当前场景下会导致所有调用weatherService的地方都需要加状态判断的冗余代码,后续新增错误类型需要修改所有调用方,维护成本高

可使用的工具库

  1. 框架原生能力:JAX-RS的ExceptionMapper(Resteasy、Jersey等实现都原生支持)、Spring Boot的@RestControllerAdvice,不需要额外引入依赖就能实现全局异常处理
  2. 简化开发:用Lombok注解减少自定义异常的样板代码
  3. 容错增强:如果要实现第三方调用失败自动重试、熔断降级,可以用Resilience4j,针对第三方500错误配置重试策略,重试失败再抛出异常返回503,能大幅提升接口可用性

代码示例

1. 自定义异常定义

// 通用第三方调用父异常
public class ThirdPartyApiException extends RuntimeException {
    private final int httpStatus;

    public ThirdPartyApiException(String message, int httpStatus) {
        super(message);
        this.httpStatus = httpStatus;
    }

    public int getHttpStatus() {
        return httpStatus;
    }
}

// 具体场景异常
public class InvalidCoordinateException extends ThirdPartyApiException {
    public InvalidCoordinateException(String message) {
        super(message, 400);
    }
}

public class LocationNotCoveredException extends ThirdPartyApiException {
    public LocationNotCoveredException(String message) {
        super(message, 404);
    }
}

public class WeatherServiceUnavailableException extends ThirdPartyApiException {
    public WeatherServiceUnavailableException(String message) {
        super(message, 503);
    }
}

2. weatherService实现

public Weather getWeather(double latitude, double longitude) {
    // 调用第三方天气API的逻辑
    Response thirdPartyResp = thirdPartyWeatherClient.getWeather(latitude, longitude);
    int status = thirdPartyResp.getStatus();
    if (status == 200) {
        return thirdPartyResp.readEntity(Weather.class);
    } else if (status == 400) {
        throw new InvalidCoordinateException("经纬度参数非法");
    } else if (status == 404) {
        throw new LocationNotCoveredException("请求位置不在服务覆盖范围内");
    } else if (status == 500) {
        throw new WeatherServiceUnavailableException("天气服务暂时不可用");
    }
    // 未知错误统一返回503
    throw new WeatherServiceUnavailableException("天气服务调用失败");
}

3. 全局异常处理器(JAX-RS版本)

@Provider
public class ThirdPartyApiExceptionMapper implements ExceptionMapper<ThirdPartyApiException> {
    @Override
    public Response toResponse(ThirdPartyApiException e) {
        // 可以封装统一的错误响应体
        ErrorResponse error = new ErrorResponse(e.getMessage());
        return Response.status(e.getHttpStatus()).entity(error).build();
    }
}

4. 原有接口代码完全不需要修改

@Path("/weather")
Response getWeather(double latitude, double longtitude) {
    Weather weather = weatherService.getWeather(latitude, longtitude);
    return wrapWithHttpOK(weather);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:15:03