目录
本文概览:通过RestTemplate来实现调用服务方提供的http接口。不需要再自己实现HttpClient。
1 背景
在系统中需要调用外部系统的http接口,将返回json解析成对象。一般逻辑是
- 首先提供定义一个HttpClient来访问http接口
- 然后通过jackson来解析返回的json串
对于这个流程,Spring 的RestTemplate已经帮我们实现了。可以直接使用。
2 返回类型
根据不同返回类型来介绍使用实例。
- List
- Map
- Object
- Json字符串
2.1 返回Object
1、服务方提供的接口的返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "ret": 0, "msg": "success", "bankQuota": [ { "frontBankCode": "4033", "bankName": "工行", "singleLimitAmount": "xx万", "dailyLimitAmount": "xx万", "monthlyLimitAmount": "无限额", "pcQuota": "单笔xx万", "orderNo": null }, { "frontBankCode": "4011", "bankName": "建行", "singleLimitAmount": "yy万", "dailyLimitAmount": "yy万", "monthlyLimitAmount": "无限额", "pcQuota": "单笔yy万", "orderNo": null } } |
2、代码
(1)使用RestTemplate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * 银行最新限额信息 * @return */ @RequestMapping("queryBankLimit") @ResponseBody public List<BankLimitVo> queryBankLimit(){ RestTemplate restTemplate = new RestTemplate(); BankLimitResponse limitResponse = restTemplate.getForObject ("https://dubai.com/xx/query?sp=12&from=0.0.0", BankLimitResponse.class); List<BankLimitVo> result = limitResponse.getBankQuota(); return result; } |
(2)定义两个对象
- 定义Response
1 2 3 4 5 6 |
public class BankLimitResponse { private int ret; private String msg; private List<BankLimitVo> bankQuota; .....getter和setter方法 } |
- Vo对象
1 2 3 4 5 6 7 8 |
public class BankLimitVo { String frontBankCode; String bankName; String singleLimitAmount; String dailyLimitAmount; String monthlyLimitAmount; .... getter和setter方法 } |
2.2 复杂的类型
如返回类型是Map<String,Map<String,Object>>,可以通过如下步骤:
- Step1 转换成String
- Step2 通过TypeReference将String转成复杂的对象。这里使用的是fastJson
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// 1.转成String类型 public Map<String, Map<String, List<Student>>> queryStudent(String name) { try { String url = "http:xxx.com/xx/xx"; String response = restTemplate.getForObject(url, String.class); Map<String, Map<String, List<Student>>> result = transferMap(response); return result; } catch (Exception e) { LOGGER.error("query error", e); return null; } } // 2.String转成复杂对象 private Map<String, Map<String, List<Student>>> transferMap(String response) { Map<String, Map<String, List<Student>>> map = JSON.parseObject(response, new TypeReference<Map<String, Map<String, List<Student>>>>() { }); return map; } |
3 参数类型
3.1 被调用接口如何接受参数
以post为例,会有如下方法
1 2 3 4 5 6 7 8 9 |
@Override public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException { } @Override public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException { } |
- 参数类型是map时,此时类似前端参数为form表单。
- 参数是Obect类型,此时相当于前端传参数是json,此时被调用的接口中必须使用@ReqeustBody
4 常见问题
4.1 “Not enough variable values available to expand”
当 url为 “http://xxxxx.com/qeury?uri=/test/{gourp}”,然后执行如下代码时,就会出现这个“Not enough variable values available to expand”错误。
1 |
OutputPage page = restTemplate.getForObject(url1, OutputPage.class) |
这个错误是因为大括号引起来的,在网上常见一个做法如下:https://stackoverflow.com/questions/21819210/using-resttemplate-in-spring-exception-not-enough-variables-available-to-expan
对应代码:
1 2 3 4 |
String sort = "{\"price\":\"desc\"}"; String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={sort}"; // 指定srot的值 OutputPage page = restTemplate.getForObject(url1, OutputPage.class, sort); |
但是我们确实把{group}当成参数,而不是变量,所以此时做法如下
1 2 3 4 |
requestUrl = “http://xxxxx.com/qeury?uri=/test/{gourp}”; UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(requestUrl); UriComponents uriComponents = builder.build(); String response = restTemplate.getForObject(uriComponents.toUri(), String.class); |
(…待完善…)