resttemplate get请求_RestTemplate 使用

5f512f30522536e737adea9c23e4348d.png

RestTemplate Rest 模板概述

带负载均衡(@LoadBalanced)的 RestTemplate 必须使用微服务名称发起请求,不能使用 ip:port
不带负载均衡(@LoadBalanced)的 RestTemplate 不能使用微服务名称发起请求,只能使用 ip:port

1、org.springframework.web.client.RestTemplate 类是 spring-web-x.x.x.RELEASE.jar 包下进行 HTTP 访问的 REST 客户端核心类。

2、Java 应用后台代码中如果想要向另外一个 Java 应用发起 Http 请求,通常使用 Apache 的 HttpClient 库来做。而 spring cloud 微服务架构中,各个微服务之间会频繁的发起 http 请求进行通信,所以 spring 对 http 请求进行了封装,以便请求使用起来更加方便。

3、RestTemplate 类能够以 rest 风格的方式,以 GET, POST, PUT, DELETE, HEAD, OPTIONS 等不同的方式向服务器发起HTTP 请求。

4、RestTemplate 对 http 的封装类似 JdbcTemplate 对 jdbc 的封装。本文环境:Java jdk 8 + Spring boot 2.1.3(spring 5.1.5)。

构造函数描述
RestTemplate()默认使用 org.springframework.http.client.SimpleClientHttpRequestFactory 客户端,底层使用 jdk 标准的 API,即 http://java.net 包下的 API,如 java.net.HttpURLConnection 等。
RestTemplate(ClientHttpRequestFactory requestFactory)ClientHttpRequestFactory 接口的实现类给出底层实现的第三方 HTTP 客户端软件。如 OkHttp3Client、以及 RibbonClient 等
RestTemplate(List<HttpMessageConverter<?>> messageConverters)HttpMessageConverter 接口的实现对象能够在HTTP消息与Java POJO之间进行数据转换。

687fdfa61ba52e75c00f21fe75b67a3e.png

5、使用 RestTemplate 非常简单,对于 Spring boot、Spring Cloud 项目,spring-boot-starter-web 组件内部已经包含了 spring-web-x.x.x.RELEASE.jar ,所以只需要将 RestTemplate 实例交由 Spring 容器管理,然后在需要的地方获取使用即可。


  1. //可以直接在启动类(@SpringBootApplication) 中进行添加,或者在 @Configuration 标注的类中添加

  2. @Bean

  3. public RestTemplate restTemplate() {

  4. //将 RestTemplate 实例交由 Spring 容器管理

  5. return new RestTemplate();

  6. }

  1. //在使用 RestTemplate 的 Controller 或者其它地方自动注入,然后使用

  2. @Resource

  3. private RestTemplate restTemplate;

Http GET 请求

方法描述
<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType)url:请求的地址,responseType:返回的数据类型,ResponseEntity 对象包含了http响应头信息、响应正文、响应状态等信息
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)uriVariables:用于设置查询参数的可变值,map 的 key 值对于url中设置的可变参数值.
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)uriVariables:专门用于处理 url 路径中的参数 @PathVariable
<T> T getForObject(URI url, Class<T> responseType)getForObject 方法是重载的方法,区别在于返回值直接是响应正文,不含响应头信息以及响应状态.
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
<T> T getForObject(String url, Class<T> responseType, Object... uriVariables)

getForEntity(URI url, Class<T> responseType)


  1. /** 接口提供方

  2. * @param uid

  3. * @param agencyId

  4. * @return

  5. */

  6. @GetMapping("getInfo")

  7. public String getInfo(@RequestParam String uid, String agencyId) {

  8. JSONObject jsonObject = new JSONObject();

  9. jsonObject.put("code", 200);

  10. jsonObject.put("uid", uid);

  11. jsonObject.put("agencyId", agencyId);

  12. return jsonObject.toString();

  13. }

  1. //接口调用方

  2. @GetMapping("test1")

  3. public String test1() {

  4. String body = null;

  5. try {

  6. URI uri = new URI("http://localhost:8080/getInfo?uid=3030&agencyId=20807");

  7. ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);

  8. //http响应状态码,如成功时返回 200

  9. int statusCodeValue = forEntity.getStatusCodeValue();

  10. //http响应的正文内容,即对方返回的数据,如 {"uid":"3030","code":200,"agencyId":"20807"}

  11. body = forEntity.getBody();

  12. //http响应的头信息,如 Content-Type=[text/plain;charset=UTF-8], Content-Length=[44], Date=[Tue, 24 Mar 2020 12:45:43 GMT]}

  13. HttpHeaders headers = forEntity.getHeaders();

  14. System.out.println("headers=" + headers + "nstatusCodeValue=" + statusCodeValue + "nbody=" + body);

  15. } catch (URISyntaxException e) {

  16. e.printStackTrace();

  17. }

  18. return body;

  19. }

getForEntity(String url, Class<T> responseType, Object... uriVariables)


  1. /**

  2. * 接口提供方

  3. * @param uid

  4. * @param agencyId

  5. * @return

  6. */

  7. @GetMapping("getData/{agencyId}/{uid}")

  8. public List<Map<String, Object>> getData(@PathVariable String uid, @PathVariable String agencyId, String info) {

  9. List<Map<String, Object>> dataMapList = new ArrayList<>(8);

  10. Map<String, Object> map = new HashMap<>(8);

  11. map.put("code", 200);

  12. map.put("uid", uid);

  13. map.put("info", info);

  14. map.put("agencyId", agencyId);

  15. dataMapList.add(map);

  16. return dataMapList;

  17. }

  1. //接口调用方

  2. @GetMapping("test2")

  3. public List<Map<String, Object>> test2() {

  4. String uri = "http://localhost:8080/getData/{agency_id}/{u_id}?info=长沙";

  5. //返回数据类型为 List 类型

  6. ResponseEntity<List> forEntity = restTemplate.getForEntity(uri, List.class, 20792, "999UP000");

  7. //http响应状态码,如成功时返回 200

  8. int statusCodeValue = forEntity.getStatusCodeValue();

  9. //http响应的正文内容,即对方返回的数据,如 {"uid":"3030","code":200,"agencyId":"20807"}

  10. List<Map<String, Object>> body = forEntity.getBody();

  11. //http响应的头信息,如 Content-Type=[text/plain;charset=UTF-8], Content-Length=[44], Date=[Tue, 24 Mar 2020 12:45:43 GMT]}

  12. HttpHeaders headers = forEntity.getHeaders();

  13. System.out.println("headers=" + headers + "nstatusCodeValue=" + statusCodeValue + "nbody=" + body);

  14. return body;

  15. }

getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)


  1. /**

  2. * 接口提供方
    *
    * @param uid

  3. * @param agencyId

  4. * @return

  5. */

  6. @GetMapping("getMessage")

  7. public JSONObject getMessage(String uid, String agencyId) {

  8. List<Map<String, Object>> dataMapList = new ArrayList<>(8);

  9. Map<String, Object> map = new HashMap<>(8);

  10. JSONObject jsonObject = new JSONObject();

  11. jsonObject.put("code", 200);

  12. jsonObject.put("uid", uid);

  13. jsonObject.put("agencyId", agencyId);

  14. return jsonObject;

  15. }

  1. //接口调用方

  2. @GetMapping("test3")

  3. public JSONObject test3() {

  4. String uri = "http://localhost:8080/getMessage?uid={uid}&agencyId={agency_id}";

  5. Map<String, Object> paramMap = new HashMap<>(4);

  6. paramMap.put("uid", "9998UYT9");

  7. paramMap.put("agency_id", 20802);

  8. //getForObject 返回数据类型为 JSONObject 类型的响应内容,即直接获取返回值.

  9. JSONObject body = restTemplate.getForObject(uri, JSONObject.class, paramMap);

  10. System.out.println(body);

  11. return body;

  12. }

6630d7395f72245c210a6baecfd05a44.png

Http Post 请求

方法描述
<T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType)url:请求的地址;request:请求的正文(body)内容,即对方 @RequestBody 参数的值,可以为 null。responseType:返回的数据类型,ResponseEntity 对象包含了http响应头信息、响应正文、响应状态等信息
<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Map<String, ?> uriVariables)uriVariables:用于设置查询参数的可变值,map 的 key 值对于url中设置的可变参数值.
<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Object... uriVariables)uriVariables:专门用于处理 url 路径中的参数 @PathVariable
T postForObject(URI url, @Nullable Object request, Class<T> responseType)getForObject 方法是重载的方法,区别在于返回值直接是响应正文,不含响应头信息以及响应状态.
T postForObject(String url, @Nullable Object request, Class<T> responseType,Map<String, ?> uriVariables)
T postForObject(String url, @Nullable Object request, Class<T> responseType,Object... uriVariables)

postForEntity(String url, @Nullable Object request,Class<T> responseType, Map<String, ?> uriVariables)


  1. /**接口提供方
    *

  2. * @param uid

  3. * @param agencyId

  4. * @return

  5. */

  6. @PostMapping("postInfo")

  7. public JSONObject postInfo(@RequestParam String uid, String agencyId) {

  8. JSONObject jsonObject = new JSONObject();

  9. jsonObject.put("code", 200);

  10. jsonObject.put("uid", uid);

  11. jsonObject.put("agencyId", agencyId);

  12. return jsonObject;

  13. }

  1. //接口调用方

  2. @GetMapping("test11")

  3. public JSONObject test11() {

  4. JSONObject body = null;

  5. String uri = "http://localhost:8080/postInfo?uid={uid}&agencyId=208071";

  6. Map<String, String> paramMap = new HashMap<>(4);

  7. paramMap.put("uid", "8899HG9");

  8. ResponseEntity<JSONObject> forEntity = restTemplate.postForEntity(uri, null, JSONObject.class, paramMap);

  9. //http响应状态码,如成功时返回 200

  10. int statusCodeValue = forEntity.getStatusCodeValue();

  11. //http响应的正文内容,即对方返回的数据,如 {"uid":"3030","code":200,"agencyId":"20807"}

  12. body = forEntity.getBody();

  13. //http响应的头信息,如 Content-Type=[text/plain;charset=UTF-8], Content-Length=[44], Date=[Tue, 24 Mar 2020 12:45:43 GMT]}

  14. HttpHeaders headers = forEntity.getHeaders();

  15. System.out.println("headers=" + headers + "nstatusCodeValue=" + statusCodeValue + "nbody=" + body);

  16. return body;

  17. }

postForObject(String url, @Nullable Object request, Class<T> responseType,Object... uriVariables)


  1. /**

  2. * 接口提供方

  3. * http://localhost:8080/postData/{agencyId}

  4. */

  5. @PostMapping("postData/{agencyId}")

  6. public List<Map<String, Object>> postData(@PathVariable String agencyId, @RequestBody List<String> ids) {

  7. List<Map<String, Object>> dataMapList = new ArrayList<>(8);

  8. Map<String, Object> map = new HashMap<>(8);

  9. map.put("code", 200);

  10. map.put("uid", ids.toArray());

  11. map.put("agencyId", agencyId);

  12. dataMapList.add(map);

  13. return dataMapList;

  14. }

  1. //接口调用方

  2. @GetMapping("test22")

  3. public List<Map<String, Object>> test22() {

  4. String uri = "http://localhost:8080/postData/{agencyId}";

  5. List<String> ids = new ArrayList<>(4);

  6. ids.add("3000L");

  7. ids.add("99UH7");

  8. ids.add("99JHG");

  9. //返回数据类型为 List 类型

  10. List<Map<String,Object>> body = restTemplate.postForObject(uri, ids, List.class, 20792);

  11. return body;

  12. }
//其余操作都是同理

RestTemplate 超时时间

1、new RestTemplate() 时默认使用 SimpleClientHttpRequestFactory 工厂,它底层默认使用 Java 原生的 HttpURLConnection API 做 Http 请求,默认 connectTimeout = -1(连接超时),readTimeout = -1(读取超时)都没有做限制,即一直等待。

08ccfb76d9dba1ec2ec2a97129621ee6.png

2、显然无限期的等待是绝不允许的,必须设置超时时间,以 SimpleClientHttpRequestFactory 工厂为例:


  1. //设置 http 连接工厂,然后将 RestTemplate 实例交由 Spring 容器管理

  2. @Bean

  3. public RestTemplate restTemplate() {

  4. //先设置 http 连接工厂的连接超时时间为 30 秒,读取超时时间为 120 秒

  5. //请求发送后,对方数据量比较大,需要长时间处理数据时,读取超时时间需要设置的长一些,否则对方还未处理完,连接就超时了。

  6. SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

  7. requestFactory.setConnectTimeout(30 * 1000);

  8. requestFactory.setReadTimeout(120 * 1000);

  9. return new RestTemplate(requestFactory);

  10. }

3、验证非常简单,请求 youtube ,铁定连不上而会超时,然后抛异常: java.net.SocketTimeoutException: Read timed out

String body = restTemplate.getForObject(" https:// ca.youtube.com/ ", String.class);

切换 OkHttpClient 客户端

1、ClientHttpRequestFactory 有多个实现类,okhttp3 作为现在最热门 http 客户端,这里就以 OkHttpClient 为例。

2、第一步项目中引入 OkHttpClient 的依赖,否则会报:java.lang.NoClassDefFoundError: okhttp3/OkHttpClient


  1. <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->

  2. <dependency>

  3. <groupId>com.squareup.okhttp3</groupId>

  4. <artifactId>okhttp</artifactId>

  5. <version>3.14.5</version>

  6. </dependency>
版本不能随意引,org.springframework.http.client.OkHttp3ClientHttpRequestFactory 类的源码上面通常有提示说明对应的OkHttp 版本,如本文 spring-web-5.0.7.RELEASE.jar 提示的 OkHttp 版本是 3.X,如果引入 4.X 则启动会失败。

3、接下来就是创建 RestTemplate 对象的时候,传入 OkHttp3ClientHttpRequestFactory 工厂即可:


  1. //设置 http 连接工厂,然后将 RestTemplate 实例交由 Spring 容器管理

  2. @Bean

  3. public RestTemplate restTemplate() {

  4. //先设置 http 连接工厂的连接超时时间为 30 秒,读取超时时间为 120 秒

  5. OkHttp3ClientHttpRequestFactory okRequestFactory = new OkHttp3ClientHttpRequestFactory();

  6. okRequestFactory.setConnectTimeout(30 * 1000);

  7. okRequestFactory.setReadTimeout(120 * 1000);

  8. return new RestTemplate(okRequestFactory);

  9. }
验证底层到底用的什么 http 客户端也很简单,仍然请求 youtube( https:// ca.youtube.com ) ,连接超时时控制层会打印异常,其中就可以看到 okhttp3.internal.xxxx 的错误信息。

4、其它如 Apache 的 HttpClient、以及 Netty、RibbonClient 等 http 客户端使用都是同理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值