用RestTemplate调用第三方提供的API接口

首先按照惯例分享一个提供免费接口的网站:
聚合数据
直接点击去自己注册个账号申请个免费的接口测试

今天用RestTemplate调一个天气预报的接口
在这里插入图片描述
申请之后记住这个key后面拼装url会用
建议直接写在配置文件里
先看API文档介绍
在这里插入图片描述
很清晰看到该接口请求方式支持get或者post
在看请求示例 :
后面带着两个请求参数 这个地方这两个参数顺序前后无所谓
下面直接来代码:
先弄个key的属性类

/**
 * 类说明: <br>
 * 〈天气预报接口key〉
 *
 * @Author: wlt
 * @Date: 2021/3/15 10:11
 */
@Data
public class WeatherProp extends BaseBean {
    /**
     * 调用接口key
     */
    private String key;

}

yml配置文件里需要加上

pangu-weather:
    weatherprop:
        key: xxxxxxxxxxxxxxxx

然后配置类

/**
 * 类说明: <br>
 * 〈天气接口属性配置〉
 *
 * @Author: wlt
 * @Date: 2021/3/15 10:36
 */
@Configuration
public class ApplicationWeatherConfig {
    @Bean
    @ConfigurationProperties(prefix = "pangu-weather.weatherprop")
    public WeatherProp weatherProp() {
        return new WeatherProp();
    }
}

以上就可以在启动的时候这个属性类就会当成一个bean注入到容器里了
接下来就是拼装这个url调用了

/**
 * 类说明: <br>
 * 〈天气预报处理程序〉
 *
 * @Author: wlt
 * @Date: 2021/3/15 10:04
 */
@Slf4j
@Component("weatherHandler")
public class WeatherHandler implements InitializingBean {
    /**
     * 调用聚合数据接口应答errcode: 0 :请求成功
     */
    public static final int RPC_CODE_SUCCESS = 0;
    /**
     * 调用聚合数据接口应答errcode: 207301 :错误的查询城市名
     */
    public static final int RPC_CODE_WRONG_CITY = 207301;
    /**
     * 调用聚合数据接口应答errcode: 207302 :查询不到该城市的相关信息
     */
    public static final int RPC_CODE_NOT_FOUND_CITY = 207302;
    /**
     * 调用聚合数据接口应答errcode: 207303 :网络错误,请重试
     */
    public static final int RPC_CODE_NETWORK_ERROR= 207303;

    @Resource(name = "weatherProp")
    private WeatherProp weatherProp;

    @Resource(name = "restTemplate")
    private RestTemplate restTemplate;
    /**
     * 请求地址
     */
    private String url;

    @Override
    public void afterPropertiesSet() throws Exception {
        StringBuilder urlSb = new StringBuilder();
        urlSb.append("http://apis.juhe.cn/simpleWeather/query?");
        urlSb.append("key=").append(weatherProp.getKey());
        this.url = urlSb.toString();
    }
    /**
     * 功能描述: <br>
     * <查询天气>
     * @Param [city]
     * @return 应答消息
     * @Author: wlt
     * @Date: 2021/3/15 11:10
     **/
    public WeatherVO weather(String city) {
        log.debug("param city : {}", city);
        String reqUrl = url + "&city=" + city;
        System.out.println(reqUrl);
        String responseStr = restTemplate.getForObject(reqUrl, String.class);
        log.debug("code: {}, responseStr : {}", city, responseStr);
        WeatherVO weather = JsonUtil.readValue(responseStr, WeatherVO.class);
        return weather;
    }

}

其实就是这么一句话完成了调用
String responseStr = restTemplate.getForObject(reqUrl, String.class);
这个地方得注意啊API返回的JSON示例

{
    "reason": "查询成功",
    "result": {
        "city": "苏州",
        "realtime": {
            "temperature": "4",
            "humidity": "82",
            "info": "阴",
            "wid": "02",
            "direct": "西北风",
            "power": "3级",
            "aqi": "80"
        },
        "future": [
            {
                "date": "2019-02-22",
                "temperature": "1/7℃",
                "weather": "小雨转多云",
                "wid": {
                    "day": "07",
                    "night": "01"
                },
                "direct": "北风转西北风"
            },
            {
                "date": "2019-02-23",
                "temperature": "2/11℃",
                "weather": "多云转阴",
                "wid": {
                    "day": "01",
                    "night": "02"
                },
                "direct": "北风转东北风"
            },
            {
                "date": "2019-02-24",
                "temperature": "6/12℃",
                "weather": "多云",
                "wid": {
                    "day": "01",
                    "night": "01"
                },
                "direct": "东北风转北风"
            },
            {
                "date": "2019-02-25",
                "temperature": "5/12℃",
                "weather": "小雨转多云",
                "wid": {
                    "day": "07",
                    "night": "01"
                },
                "direct": "东北风"
            },
            {
                "date": "2019-02-26",
                "temperature": "5/11℃",
                "weather": "多云转小雨",
                "wid": {
                    "day": "01",
                    "night": "07"
                },
                "direct": "东北风"
            }
        ]
    },
    "error_code": 0
}

在这里插入图片描述
result其实是个Object
返回的实体类

/**
 * 类说明: <br>
 * 〈返回json数据〉
 *
 * @Author: wlt
 * @Date: 2021/3/15 10:02
 */
@Data
public class WeatherVO extends BaseBean {
    private static final long serialVersionUID = 6788688600990722529L;
    /**
     * <返回码,0为查询成功>
     **/
    private int error_code;
    /**
     * <返回说明>
     **/
    private String reason;
    /**
     * <返回结果集>
     **/
    private Object result;
}

接下来就是Controller
注意我用的是DDD领域驱动设计模式写起来很麻烦 我就简单复制下代码你们参考一下即可

 /**
     * 功能描述: <br>
     * <根据城市查询天气>
     * @Param [form]
     * @return 应答消息
     * @Author: wlt
     * @Date: 2021/3/15 14:12
     **/
    @PostMapping(path = "/company/workflow/drivelog/queryCityWeather", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseMessage<WeatherDTO> queryCityWeather(@RequestBody WeatherForm form) {
        ResponseMessage<WeatherEntity> result = drivelogAppService.queryCityWeather(form);
        if (ResponseCheckUtil.failed(result)) {
            return ResponseMessageUtil.genResult(result.getCode(), result.getMsg());
        }
        WeatherDTO weatherDTO = DrivelogAssembler.toWeatherDTO(result.getData());
        return ResponseMessageUtil.genSuccessResult(weatherDTO);
    }

APPService代码

 /**
     * 功能描述: <br>
     * <根据城市查询天气>
     * @Param [city]
     * @return 应答消息
     * @Author: wlt
     * @Date: 2021/3/15 11:23
     **/
    public ResponseMessage<WeatherEntity> queryCityWeather(WeatherForm form) {
        return drivelogDomainService.queryCityWeather(form);
    }

DomainService代码

 /**
     * 功能描述: <br>
     * <根据城市查询天气>
     * @Param [city]
     * @return 应答消息
     * @Author: wlt
     * @Date: 2021/3/15 11:23
     **/
    public ResponseMessage<WeatherEntity> queryCityWeather(WeatherForm form) {
        //调聚合数据接口查询天气预报
        WeatherVO response = weatherHandler.weather(form.getCity());
        Integer errorCode = Integer.valueOf(response.getError_code());
        if (errorCode != WeatherHandler.RPC_CODE_SUCCESS) {
            Res01012Weather res01012Weather = weatherMap.get(errorCode);
            if (res01012Weather != null) {
                return ResponseMessageUtil.genResult(res01012Weather);
            }
            return ResponseMessageUtil.genFailResult();
        }
        //object转实体类
        Object result = response.getResult();
        ObjectMapper objectMapper = new ObjectMapper();
        WeatherEntity weatherEntity = objectMapper.convertValue(result, WeatherEntity.class);
        return ResponseMessageUtil.genSuccessResult(weatherEntity);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        weatherMap = new HashMap<>();
        weatherMap.put(WeatherHandler.RPC_CODE_WRONG_CITY,Res01012Weather.RPC_CODE_WRONG_CITY);
        weatherMap.put(WeatherHandler.RPC_CODE_NOT_FOUND_CITY,Res01012Weather.RPC_CODE_NOT_FOUND_CITY);
        weatherMap.put(WeatherHandler.RPC_CODE_NETWORK_ERROR,Res01012Weather.RPC_CODE_NETWORK_ERROR);
    }

我把API上的错误码改成了我们自己项目设定的错误码
前面需要定义一个全局的map
private Map<Integer, Res01012Weather> weatherMap;
解释:
afterPropertiesSet这个方法来自接口InitializingBean
源码注释:
设置所有bean属性后,由包含的{@code BeanFactory}调用
并满意{@link BeanFactoryAware},{@ code ApplicationContextAware}等。

此方法允许Bean实例对其整体执行验证 设置了所有bean属性后,进行配置和最终初始化。 如果配置错误(例如无法设置 必要属性),或者如果初始化由于任何其他原因而失败

测试接口:

在这里插入图片描述

控制台打印日志

在这里插入图片描述

### 使用 `RestTemplate` 调用外部 RESTful API 为了调用外部 RESTful API,`RestTemplate` 提供了简便的方式来进行HTTP请求。通过实例化 `RestTemplate` 对象并利用其内置方法,能够轻松完成对外部服务的调用。 #### 发起 GET 请求获取 JSON 数据 当目标是从远程服务器检索数据时,可以采用如下方式构建GET请求: ```java // 初始化 RestTemplate 实例 RestTemplate restTemplate = new RestTemplate(); // 定义要访问的目标URL String url = "https://api.example.com/data"; // 执行GET请求并将返回的结果映射到指定的对象类型(这里假设为DataClass) ResponseEntity<DataClass> response = restTemplate.getForEntity(url, DataClass.class); // 输出状态码和响应体中的内容 System.out.println("Status Code: " + response.getStatusCode()); System.out.println("Body: " + response.getBody()); ``` 此段代码展示了如何定义 URL 并使用 `getForEntity()` 方法发出 GET 请求,同时指定了期望接收的数据模型类 `DataClass`[^1]。 #### POST 请求发送 JSON 数据至服务器 对于向服务器提交数据的情况,则可采取POST请求的形式: ```java // 创建待发送的数据实体对象 DataToPost dataToSend = new DataToPost(); dataToSend.setField1("value"); dataToSend.setField2(123); // 设置目标地址 String postUrl = "https://api.example.com/postEndpoint"; // 构建HttpHeaders用于设置Content-Type等头部信息 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); // 将数据封装成 HttpEntity HttpEntity<DataToPost> requestEntity = new HttpEntity<>(dataToSend, headers); // 发送POST请求,并期待返回特定类型的响应 ResponseEntity<String> postResponse = restTemplate.postForEntity(postUrl, requestEntity, String.class); ``` 上述例子说明了怎样准备要上传的信息结构 `DataToPost` ,并通过 `postForEntity()` 函数传递给远端API接口[^4]。 #### 处理异常情况 考虑到网络通信过程中可能出现的各种错误状况,在实际应用中应当加入适当的异常处理机制: ```java try { ResponseEntity<?> response = restTemplate.exchange( url, HttpMethod.GET, null, Object.class ); } catch (HttpClientErrorException | HttpServerErrorException e) { // 捕获客户端或服务器级别的HTTP错误 System.err.println("Error status code: " + e.getRawStatusCode()); System.err.println("Error message: " + e.getResponseBodyAsString()); } ``` 这段代码片段体现了针对可能发生的 HTTP 错误所设计的捕捉逻辑,有助于提高程序健壮性[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值