SpringBoot使用RestTemplate访问第三方接口

SpringBoot使用RestTemplate访问第三方接口目录前言介绍使用前言介绍使用

大家好,又见面了,我是你们的朋友全栈君。

养成习惯,先赞后看!!!

前言

相信大家都知道如何在自己的项目里面调用自己的接口,只需要调用自己项目里面接口特定的URL地址就行了,但是如果是调用其他项目的接口呢,这时候如果是直接调用的话,很明显我们是不能够调用的.肯定是要通过某个工具才能够进行访问的.我们可以通过下面这张图来理解.
在这里插入图片描述

介绍

HTTPClient与RestTemplate

在RestTemplate出现之前,一般都是通过HTTPClient进行访问,但是HTTPClient访问又十分的麻烦,这里贴一个样例让大家先感受 一下HTTPClient整个的请求方式

@Test
	public String test() throws ClientProtocolException, IOException { 
   
	    //1、创建httpClient
        CloseableHttpClient client = HttpClients.createDefault();
        //2、封装请求参数
        List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
        //这里默认都是String,String,但是之后会对相应的数据类型进行转换
        list.add(new BasicNameValuePair("username", "name"));
        //3、转化参数
        String params = EntityUtils.toString(new UrlEncodedFormEntity(list, Consts.UTF_8));
        //4、创建HttpGet请求
        HttpGet httpGet = new HttpGet("url接口地址"+"?"+params);
        CloseableHttpResponse response = client.execute(httpGet);
        //5、获取实体
        HttpEntity entity = response.getEntity();
        //将实体装成字符串
        String string = EntityUtils.toString(entity);
        response.close();
        return result;
	}

其实整体逻辑还是比较清晰的就是整体的代码量比较多,使得代码比较的臃肿,之后推出了RestTemplate之后,将访问接口的代码极度减少,更加方便我们的使用,这里我们使用RestTemplate之后看看上述的接口我们编写需要什么样的步骤.


 @Test
	public String test()  { 
   
	     HashMap<String,Object> map = new HashMap<>();
         map.put("typeId",1);
         //三个参数分别为 接口地址,返回数据类型,参数列表
         String result= restTemplate.getForObject("url接口地址", String.class, map);
         return result;
	}

不对比的话,我们还觉得httpclient还是比较好用的,但是对比完之后我们就可以发现,httpclient是个啥啊,这代码量搞得只剩原来的约三分之一.
在这里插入图片描述并且相对来说RestTemplate也极度的减少了流程代码,是的我们只需要专注于核心的流程业务即请求接口地址是啥,请求的参数是什么这两个最最最重要的步骤,其他的客户端的创建,请求参数转换,连接关闭这些都不需要我们再考虑,着实方便了我们的开发.

使用

既然我们已经比较完了,那么我们就要来看看我们到底应该如何使用RestTemplate了.

第一步-注入bean

既然我们想使用RestTemplate,那么我们就必须要将RestTemplate注入到Spring容器之中,所以我们在启动类中注入我们的RestTemplate

@Bean //必须new 一个RestTemplate并放入spring容器当中,否则启动时报错
    public RestTemplate restTemplate() { 
   
        RestTemplate restTemplate = new RestTemplate();
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
        httpRequestFactory.setConnectTimeout(30 * 3000);
        httpRequestFactory.setReadTimeout(30 * 3000);
        restTemplate.setRequestFactory(httpRequestFactory);
        return restTemplate;
    }

这样我们就能够正常的使用RestTemplate

第二步-调用方法

这里我们就可以在我们需要调用第三方接口的controller里面注入我们RestTemplate了

 @Autowired
 RestTemplate restTemplate;

这时候我们来看看restTemplate都有哪些方法也可以理解为他有哪些请求第三方接口的方法
首先我们可以先看到Get请求有这么些方法
在这里插入图片描述

Post请求有这么些方法
在这里插入图片描述
这么些方法其实就够我们用了.

getForEntity与getForObject的区别

接下来我们就来分析一下源码,看看这些方法都有什么样的区别,这里以 get请求 为例,post请求类似,大家可以自行查阅
其实方法主要分为 两大类 一类就是 getForEntity ,另外一类就是 getForObject

我们首先区分提下这两个大类的区别,这里我们将两段代码贴出来对比着看
首先我们来看 第一个不同 的地方:
在这里插入图片描述
我们首先可以看到就是两者的 返回类型是不一样 的,我们可以看到getForEntity的返回类型是规定死的,只能是responseEntity,但是responseEntity里面包含的数据是可以变化的,getForObject的返回类型则是可以变化的,也就是自定义的意思.

接着我们来看第二个不同的地方:
在这里插入图片描述
getForObject相对于getForEntity来说,多了一步类型转换的步骤,其实可以理解成getForObject对getForEntity获得的数据进行了 更深层次的一次封装 ,只让用户注重于他们所注重的数据本身,将其他一些无关紧要的数据,比如说 请求头,响应状态 这些数据全部都隐藏起来,只让用户看到他们想要的数据,就比如说查出来的信息

说了这么些不同,还是用一个例子来帮助大家更好的理解这两点不同吧.同样都是查询某一个信息集合

我们先通过 getForEntity 实现看一下

@GetMapping("/testRestTemplate")
@ApiOperation("测试RestTemplate")
@Scheduled(fixedRate = 5000)
public ApiResult testRestTemplate() throws ClientProtocolException, IOException{ 
   
    HashMap<String,Object> map = new HashMap<>();
    map.put("typeId",1);
    ResponseEntity<String> responseEntity=restTemplate.getForEntity("接口地址", String.class, map);
    String boby=responseEntity.getBody();
    JSONObject jsonObject = JSONObject.parseObject(boby);
    List<AlertInfo> alertInfoByTypeIdList= (List<AlertInfo>) jsonObject.get("data");
    System.out.println("*****************************************************");
    System.out.println("当前时间:"+ LocalTime.now());
    System.out.println(responseEntity);
    System.out.println(boby);
    System.out.println(alertInfoByTypeIdList);
    return ApiResult.ok(alertInfoByTypeIdList);
}

我们来看看运行之后的结果:
在这里插入图片描述
首先我们先来看打印出来的最原始的responseEntity数据
在这里插入图片描述
包含了我们需要的数据以及响应状态以及请求头等各种信息
如下图所示,可以获取到如下的信息.
在这里插入图片描述

接着我们再来看看responseEntity的主体数据boby数据
在这里插入图片描述
我们明显看到这就是responseEntity数据中的一部分

最后我们alertInfoByTypeIdList数据,这部分数据是我们已经通过JSONObject将body数据解析完成之后的样子
在这里插入图片描述
可以看到数据已经是正经的json格式了.

接下来我们在对比一下通过 getForObject 实现之后的效果:

@GetMapping("/testRestTemplate")
@ApiOperation("测试RestTemplate")
@Scheduled(fixedRate = 5000)
public ApiResult testRestTemplate() throws ClientProtocolException, IOException{ 
   
    HashMap<String,Object> map = new HashMap<>();
        map.put("typeId",1);
        String result= restTemplate.getForObject("接口地址", String.class, map);
        JSONObject jsonObject = JSONObject.parseObject(result);
        List<AlertInfo> alertInfoByTypeIdList= (List<AlertInfo>) jsonObject.get("data");
        System.out.println("*****************************************************");
        System.out.println("当前时间:"+ LocalTime.now());
        System.out.println(result);
        System.out.println(alertInfoByTypeIdList);
        return ApiResult.ok(alertInfoByTypeIdList);
}

我们来看看打印后的结果:
在这里插入图片描述
这里我们先来看一下最原始的返回数据result,可以看到数据就是我们原来定义好的返回类型
在这里插入图片描述
不再包含那些杂七杂八的数据了.

之后我们再来看一下通过JSONObject解析之后的数据
在这里插入图片描述
可以看到也已经是正经的json的数据格式了.
通过上面的对比之后我们能够发现,getForObject相对来说能够更加友好的将我们需要的数据传输过来,毕竟已经 对getForEntity传输过来的数据进行了一次封装了 .并且再抛出了打印这些代码后,我们能够发现整体的代码也变得更加的 简洁 .

get请求下的方法比较

这里我们就拿 get请求 来举例,post类似,大家可以自行查看.

其实当我们看到getForEntity的三个重载方法的时候我们就能知道他们只是 请求参数有所不同 ,并且主要不同的参数就是第三个参数,接下来我们详细说一下.

  • getForEntity(String url, Class<T> responseType, Object... uriVariables)
@Override
	public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
			throws RestClientException { 
   

		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
	}

我们看到Object的时候我们就能知道,如果请求的时候,请求参数是我们所定义的一个对象的话,那么我们就可以运用该接口,比如说我们执行新增某个对象的时候我们就可以使用该方法,举例如下:

User user=new User();
String result= restTemplate.getForObject("接口地址", String.class, user);
  • getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
@Override
	public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
			throws RestClientException { 
   

		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
	}

该方法就用于我们请求的时候需要传入参数,但是这个参数并不属于我们所创建的任何对象,可能只是单单几个参数,就好比我们登陆,我们就需要传给后台username和password,我们不可能单独为了这两个参数在创建一个对象的,所以在这种情况下我们可以使用该方法.并且这里支持我们使用 HashMap<String,Object> 不像httpclient那样只支持 HashMap<String,String> 这就使得我们可以直接定义数据的类型,不需要像httpclient那样还需要多一步数据类型转换的步骤,更加的方便.
举例如下:

HashMap<String,Object> map = new HashMap<>();
map.put("userId",2293557957);
map.put("password","1234567");
String result= restTemplate.getForObject("接口地址", String.class, map);
  • getForEntity(URI url, Class<T> responseType)
@Override
	public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException { 
   
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor));
	}

这种很明显就是我们直接发请求,并不需要我们带任何参数,就好比我们需要获取所有的用户,我们只需要请求该接口,获取所有的用户数据就行了,并不需要我们在传入任何的参数.
举例如下:

String result= restTemplate.getForObject("接口地址", String.class);

上面的讲完之后我们就可以类比到getForObject里面,逻辑其实是一样的.

  • getForObject(String url, Class<T> responseType, Object... uriVariables)
@Override
	@Nullable
	public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { 
   
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
	}
  • getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
@Override
	@Nullable
	public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException { 
   
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
	}	
  • getForObject(URI url, Class<T> responseType)
@Override
	@Nullable
	public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException { 
   
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
	}	

这样我们使用RestTemplate访问第三方接口就完成了.

第三步-配置字符集,解决乱码

但是还需要注意一点,如果我们请求回来的数据里面包含中文的话,那么我们就需要重新配置一下字符集,否则中文是会乱码的,就如下图所示:
在这里插入图片描述
在我们注入的的RestTemplate添加下面这段修改字符集的代码:

 @Bean //必须new 一个RestTemplate并放入spring容器当中,否则启动时报错
    public RestTemplate restTemplate() { 
   
        RestTemplate restTemplate = new RestTemplate();
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
        httpRequestFactory.setConnectTimeout(30 * 3000);
        httpRequestFactory.setReadTimeout(30 * 3000);
// //修改字符集
        List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
        for (HttpMessageConverter<?> httpMessageConverter : list) { 
   
            if (httpMessageConverter instanceof StringHttpMessageConverter){ 
   
                ((StringHttpMessageConverter)
                        httpMessageConverter).setDefaultCharset(Charset.forName("utf-8"));
                break;
            }
        }
        restTemplate.setRequestFactory(httpRequestFactory);
        return restTemplate;
    }

在这里插入图片描述

都看到这儿了,如果觉得对你有帮助的话,可以关注我的公众号,新人up需要你的支持!!!
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132048.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • api接口文档html模板,开发接口文档-api文档模板

    api接口文档html模板,开发接口文档-api文档模板1、XXX项目接口文档版本控制信息版本日期描述作者V1.02018-8-13创建XXX1获取所有字段1.1获取所有字段请求地址:/session/field/findAll请求参数参数名必填字段类型描述name是String根据名称筛选响应code10000成功,-1系统错误,10001必填参数为空message响应描述result如响应例子请求例子:http:/127.0.0.1:8080/…

  • CentOS中设置系统级代理

    CentOS中设置系统级代理YUM代理设置 编辑/etc/yum.conf,在最后加入#Proxyproxy=http://username:password@proxy_ip:port/ 也可以使用proxy_username和proxy_password来配置代理的用户名和密码 这样的配置完成后,所有的用户在使用yum时,都会使用代理,可以说是全局代理。 如果需要为单独的用户配置

  • 二次与三次B样条曲线c++实现

    二次与三次B样条曲线c++实现B样条曲线构建一条平滑曲线,接近而不通过控制点(首尾点除外)。如图B样条曲线从Bezier曲线演变而来,了解B样条曲线首先得了解Bezier曲线。对于平面上的三个点P0,P1,P2,其坐标分别是(x0,y0)、(x1,y1)、(x2,y2)。二次Bezier曲线用一…

  • 录取为2021年同济大学秋季博士研究生(电子与信息工程学院计算机科学与技术)

    录取为2021年同济大学秋季博士研究生(电子与信息工程学院计算机科学与技术)本来不想回忆往事,读博路上有点坎坷!!遇人不淑,时运不济,还好也遇到一些特别好的老师!同学帮忙。非常感谢这些老师的帮忙。首先是2020年10月份,我硕士生博导朱老师,告诉我他没博士招生名额,但有资格,这个吉大计算机比较特殊,每年博导重新排名,一年一考核,按照分来分博士名额,我老师最后一名,院长副院长有要两个名额的!这里面不方便多说,最后就是我老师今年21招不了博士,到我这卡壳一年,也特别遗憾没能读朱老师的博士。接下来沉沦了两天,10月10号左右吧,开始疯狂联系吉大别的博导,还好联系了几位,其中一z姓老

  • 8000401a错误解决方式(Excel)

    8000401a错误解决方式(Excel)前一阵子做开发须要用到Excel和Word编程,本人用的是Vista系统,开发环境是VS2005和Office2007,測试无不论什么问题,但是到部署的时候出现了一些令人非常头痛的问题,老是会出现比如:检索COM类工厂中CLSID为{000209FF-0000-0000-C000-000000000046}的组件时失败,原因是出现下面错误:8000401a。的错误,在网上查…

  • boost::string or boost::regex

    boost::string or boost::regex

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号