记录:288

场景:基于Spring Boot应用RestTemplate调用http请求。使用RestTemplate调用服务端发布的POST、GET、HEAD、PUT、PATCH、DELETE、OPTIONS请求,以及对TRACE请求的验证。使用RestTemplate提供的不同方法调用服务端发布的POST、GET请求。

版本:

Spring Boot 2.6.3
Spring Framework 5.3.15
Spring Cloud 2021.0.1

一、基础

本例应用RestTemplate调用http请求是基于HTTP协议。

1.名词

名词内容取自网络,聚合而成。

1.1 HTTP协议

(1)超文本传输协议,即HyperText Transfer Protocol。

(2)用于从服务器传输超文本到本地浏览器的传送协议。

(3)基于TCP/IP通信协议来传递数据。

(4)HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。

1.2 HTTPS协议

(1)超文本传输安全协议,即HyperText Transfer Protocol Secure。

(2)一种通过计算机网络进行安全通信的传输协议。

(3)HTTPS 经由 HTTP 进行通信,利用 SSL/TLS 来加密数据包,主要目的是提供对网站服务器的身份认证,保护交换资料的隐私与完整性。

1.3 TCP/IP协议

(1)传输控制协议/网际协议即Transmission Control Protocol/Internet Protocol。

(2)计算机必须遵守的规则的描述,只有遵守这些规则,计算机之间才能进行通信。

(3)TCP/IP四层模型:网络接口层、网络层、传输层、应用层。

1.4 OSI参考模型(OSI七层模型)

(1)Open System Interconnection,即OSI参考模型。

(2)国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系。

(3)物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

1.5 SSL/TLS协议

(1)SSL,安全套接字层,即Secure Sockets Layer。

(2)TLS,安全传输层安全,即Transport Layer Security。

(3)用于保障通信数据传输安全,利用数据加密技术,可确保数据在网络上传输过程中不会被截取。用于在两个通信应用程序之间提供保密性和数据完整性。

1.6 URI和URL

(1)URI: 统一资源标识符,即Uniform Resource Identifier。是一个用于标识某一互联网资源名称的字符串。

(2)URL: 统一资源定位系统,即Uniform Resource Locator。是因特网的万维网服务程序上用于指定信息位置的表示方法。是WWW的统一资源定位标志,就是指网络地址。

(3)URL是一种URI,它标识一个互联网资源,并指定对其进行操作或获取该资源的方法。

2.HTTP报文格式

2.1 客户端请求消息格式

客户端请求消息格式:

请求行、请求头部、空行和请求数据

2.2 服务端响应消息格式

服务端响应消息格式:

状态行、响应头部、空行和响应正文

3.GET请求和POST请求报文

使用报文截取工具截取报文,可以直观感受报文格式。本例使用Postman工具发起请求。

3.1 GET请求报文

请求URL:

http://127.0.0.1:19091/server/comm/f3/HangZhou20220721

(1)客户端请求报文

java springboot调用钉钉接口 springboot调用http接口_客户端

(2)服务端响应报文

java springboot调用钉钉接口 springboot调用http接口_服务端_02

3.2 POST请求报文

请求URL:

http://127.0.0.1:19091/server/comm/f1

 入参:

{
  "userName":"HangZhou20220721",
  "tradeName":"Vue进阶教程"
}

(1)客户端请求报文

java springboot调用钉钉接口 springboot调用http接口_客户端_03

 (2)服务端响应报文

java springboot调用钉钉接口 springboot调用http接口_服务端_04

4.Spring对http请求报文封装对应的类

本例只给出类名和类的属性,不给出方法。

4.1 HttpHeaders

HttpHeaders,即org.springframework.http.HttpHeaders。

HttpHeaders,实现MultiValueMap接口,org.springframework.util.MultiValueMap。

MultiValueMap接口,继承java.util.Map接口。

从以上可以确定,HttpHeaders存储请求头数据以Key,Value键值对为基础型式。

HttpHeaders定义属性

(1)以public static final修饰的属性有62个,基本上涵盖对请求头常用属性设置。以下列出部分。

public static final String ACCEPT = "Accept";
public static final String ACCEPT_CHARSET = "Accept-Charset";
public static final String ACCEPT_ENCODING = "Accept-Encoding";
public static final String ACCEPT_LANGUAGE = "Accept-Language";
......
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
......
public static final String AUTHORIZATION = "Authorization";
......
public static final String CONTENT_TYPE = "Content-Type";
.......
final MultiValueMap<String, String> headers;

(2)定义final MultiValueMap<String, String> headers;提供给客户端设置。提供了set和add方法去设置请求头,例如:

//直接add或者set到headers属性中
public void add(String headerName, @Nullable String headerValue) {
    this.headers.add(headerName, headerValue);
}
public void addAll(String key, List<? extends String> values) {
    this.headers.addAll(key, values);
}
public void addAll(MultiValueMap<String, String> values) {
    this.headers.addAll(values);
}
public void set(String headerName, @Nullable String headerValue) {
    this.headers.set(headerName, headerValue);
}
public void setAll(Map<String, String> values) {
    this.headers.setAll(values);
}
//直接设置属性,最终也会写入headers
public void setCacheControl(@Nullable String cacheControl) {
   this.setOrRemove("Cache-Control", cacheControl);
}

4.2 HttpEntity

HttpEntity,即org.springframework.http.HttpEntity。

请求头(响应头):HttpHeaders,即org.springframework.http.HttpHeaders。

请求体(响应体):T body,T匹配传入的对象类型。

只提供HttpEntity的属性,不提供方法,细节移步源码。

public class HttpEntity<T> {
  private final HttpHeaders headers;
  @Nullable
  private final T body;
}

4.3 RequestEntity

RequestEntity,即org.springframework.http.RequestEntity。

RequestEntity继承HttpEntity。

只提供RequestEntity的属性,不提供方法,细节移步源码。

public class RequestEntity<T> extends HttpEntity<T> {
  @Nullable
  private final HttpMethod method;
  @Nullable
  private final URI url;
  @Nullable
  private final Type type;
}

由于RequestEntity继承HttpEntity,把属性都写到一起,就直观的体现了请求消息报文格式。

public class RequestEntity<T> {
  @Nullable
  private final HttpMethod method;
  @Nullable
  private final URI url;
  @Nullable
  private final Type type;
  private final HttpHeaders headers;
  @Nullable
  private final T body;
}

4.4 ResponseEntity

ResponseEntity,即org.springframework.http.ResponseEntity。

ResponseEntity继承HttpEntity。

只提供ResponseEntity的属性,不提供方法,细节移步源码。

public class ResponseEntity<T> extends HttpEntity<T> {
  private final Object status;
}

由于ResponseEntity继承HttpEntity,把属性都写到一起,就直观的体现了响应消息报文格式。

public class ResponseEntity<T>{
  private final Object status;
private final HttpHeaders headers;
  @Nullable
  private final T body;
}

5.几个关于http请求常用常量类

几个关于http请求常用常量类

HttpMethod,即org.springframework.http.HttpMethod,提供8个请求方法枚举。

HttpStatus,即org.springframework.http.HttpStatus,提供68个已经定义好状态,比如200代表OK;405代表Method Not Allowed。

MediaType,即org.springframework.http.MediaType,列举了http传输媒体类型,比如application/json等。

二、RestTemplate支持的7种请求和TRACE请求

在Spring的HttpMethod中提供了8中方法如下:

POST,GET,HEAD,PUT,PATCH,DELETE,OPTIONS,TRACE

但是,RestTemplate使用HttpMethod.TRACE时,抛出客户端异常错误,应该是不支持。

归来总结:

POST、PUT、PATCH、TRACE,归为一类,入参都需要传入请求体。

GET、HEAD、DELETE、OPTIONS,归为一类,入参不需要传入请求体。

1.POST请求服务端与客户端

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 1.处理POST请求
  */
 @PostMapping("/f1")
 public Object f1(@RequestBody Object obj) {
  log.info("Restful2Controller->f1,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f1,处理业务.");
  log.info("Restful2Controller->f1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f1();
 }
  /**
 * 1.POST请求客户端
 */
public static void f1() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest2/f1";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.postForObject(postUrl, entity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
}
}

2.GET请求服务端与客户端

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 2.处理GET请求
  */
 @GetMapping("/f2")
 public Object f2(@RequestParam("obj") String obj) {
  log.info("Restful2Controller->f2,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f2,处理业务.");
  log.info("Restful2Controller->f2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f2();
 }
 /**
 * 2.GET请求客户端
 */
 public static void f2() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest2/f2";
  String obj = "Vue进阶教程";
  String para = "?obj=" + obj;
  getUrl = getUrl + para;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.getForObject(getUrl, String.class);
  System.out.println("从服务端返回结果: " + resultData);
}
}

3.HEAD请求服务端与客户端

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 3.处理HEAD请求
  */
 @RequestMapping(value = "/f3", method = RequestMethod.HEAD)
 public Object f3(@RequestParam("obj") String obj) {
  log.info("Restful2Controller->f3,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f3,处理业务.");
  log.info("Restful2Controller->f3,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f3();
 }
 /**
 * 3.HEAD请求客户端
 */
 public static void f3() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest2/f3";
  String obj = "Vue进阶教程";
  String para = "?obj=" + obj;
  getUrl = getUrl + para;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  HttpHeaders resultData = restTemplate.headForHeaders(getUrl);
  System.out.println("从服务端返回结果: " + resultData);
}
}

4.PUT请求服务端与客户端

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 4.处理PUT请求
  */
 @PutMapping("/f4")
 public Object f4(@RequestBody Object obj) {
  log.info("Restful2Controller->f4,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f4,处理业务.");
  log.info("Restful2Controller->f4,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f4();
 }
 /**
 * 4.PUT请求客户端
 */
 public static void f4() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest2/f4";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  restTemplate.put(postUrl, entity);
  System.out.println("从服务端返回结果: put请求返回类型为void");
}
}

5.PATCH请求服务端与客户端

注意:处理PATCH请求时,在创建RestTemplate时,需要注入ClientHttpRequestFactory实现类HttpComponentsClientHttpRequestFactory。因为默认实现类SimpleClientHttpRequestFactory不支持PATCH方法。

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 5.处理PATCH请求
  */
 @PatchMapping("/f5")
 public Object f5(@RequestBody Object obj) {
  log.info("Restful2Controller->f5,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f5,处理业务.");
  log.info("Restful2Controller->f5,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f5();
 }
 /**
 * 5.PATCH请求客户端
 */
 public static void f5() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest2/f5";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  HttpComponentsClientHttpRequestFactory requestFactory =
          new HttpComponentsClientHttpRequestFactory();
  requestFactory.setConnectTimeout(1000 * 6);
  requestFactory.setReadTimeout(1000 * 6);
  RestTemplate restTemplate = new RestTemplate(requestFactory);
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.patchForObject(postUrl, entity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
}
}

6.DELETE请求服务端与客户端

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 6.处理DELETE请求
  */
 @DeleteMapping("/f6")
 public Object f6(@RequestParam("obj") String obj) {
  log.info("Restful2Controller->f6,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f6,处理业务.");
  log.info("Restful2Controller->f6,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f6();
 }
/**
 * 6.DELETE请求客户端
 */
public static void f6() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest2/f6";
  String obj = "Vue进阶教程";
  String para = "?obj=" + obj;
  getUrl = getUrl + para;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  restTemplate.delete(getUrl);
  System.out.println("从服务端返回结果: delete请求返回类型为void");
}
}

7.OPTIONS请求服务端与客户端

注意,在调用OPTIONS时,服务端注入HttpServletResponse,为了设置响应头信息,只有设置了响应头,OPTIONS的客户端才能获取到具体值。

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
  @Autowired
  private HttpServletResponse response;
 /**
  * 7.处理OPTIONS请求
  */
 @RequestMapping(value = "/f7", method = RequestMethod.OPTIONS)
 public Object f7(@RequestParam("obj") String obj) {
  log.info("Restful2Controller->f7,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f7,处理业务.");
  log.info("Restful2Controller->f7,返回.");
  response.setHeader("Allow","POST,GET");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f7();
 }
 /**
 * 7.OPTIONS请求客户端
 */
 public static void f7() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest2/f7";
  String obj = "Vue进阶教程";
  String para = "?obj=" + obj;
  getUrl = getUrl + para;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  Set<HttpMethod> resultData = restTemplate.optionsForAllow(getUrl);
  System.out.println("从服务端返回结果: " + resultData);
}
}

8.TRACE请求服务端与客户端

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest2")
public class Restful2Controller {
 /**
  * 8.处理TRACE请求
  */
 @RequestMapping(value = "/f8", method = RequestMethod.TRACE)
 public Object f8(@RequestBody Object obj) {
  log.info("Restful2Controller->f8,接收参数,obj = " + obj.toString());
  log.info("Restful2Controller->f8,处理业务.");
  log.info("Restful2Controller->f8,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils8Method {
 public static void main(String[] args) throws Exception {
   f8();
 }
 /**
 * 8.TRACE请求客户端
 * 注意:
 *     RestTemplate使用HttpMethod.TRACE时,
 *     抛出客户端异常错误,应该是不支持
 */
 public static void f8() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest2/f8";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  List<HttpMethod> allowedMethods = new ArrayList<>();
  allowedMethods.add(HttpMethod.TRACE);
  headers.setAccessControlAllowMethods(allowedMethods);
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  ResponseEntity<String> resultData = restTemplate.exchange(postUrl,
          HttpMethod.TRACE, entity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
}
}

三、POST请求和GET请求

针对POST请求和GET请求这两个常用请求,RestTemplate支持的各种场景给出示例。

1.POST请求

1.1 POST请求方式1(postForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.处理POST请求
  * 入参使用@RequestBody封装为对象
  */
 @PostMapping("/f1")
 public Object f1(@RequestBody Object obj) {
  log.info("RestfulController->f1,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f1,处理业务.");
  log.info("RestfulController->f1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1();
 }
/**
  * 1.POST请求客户端
  * 服务端入参: 使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForObject
  * 客户端入参:
  *   使用HttpEntity封装,
  *   请求头(headers): HttpHeaders
  *   请求体(body): String类型的JSON字符串
  * 客户端返回值: String类型
  */
 public static void f1() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest/f1";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.postForObject(postUrl, entity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.2 POST请求方式2(postForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
  /**
  * 1.1处理POST请求
  * 入参为字符串
  */
 @PostMapping("/f1_1")
 public Object f1_1(String obj) {
  log.info("RestfulController->f1_1,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f1_1,处理业务.");
  log.info("RestfulController->f1_1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1_1();
 }
 /**
  * 1.1 POST请求客户端
  * 服务端入参: 不使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForObject
  * 客户端入参:
  *   URL中使用占位符传参,String类型的JSON字符串
  * 客户端返回值: String类型
  */
 public static void f1_1() throws Exception {
  // 1.请求URL,带占位符
  String postUrl = "http://127.0.0.1:19091/server/rest/f1_1?&obj={json}";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.postForObject(postUrl, null, String.class, json);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.3 POST请求方式3(postForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.2处理POST请求
  * 入参obj01使用@RequestBody封装为对象
  * 入参obj02字符串
  */
 @PostMapping("/f1_2")
 public Object f1_2(@RequestBody Object obj01, String obj02) {
  log.info("RestfulController->f1_2,接收参数,obj01 = " + obj01.toString());
  log.info("RestfulController->f1_2,接收参数,obj02 = " + obj02.toString());
  log.info("RestfulController->f1_2,处理业务.");
  log.info("RestfulController->f1_2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1_2();
 }
 /**
  * 1.2 POST请求客户端
  * 服务端入参:
  *   obj01使用@RequestBody注解封装,
  *   obj02只传递JSON字符串,不能使用@RequestBody注解,
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForObject
  * 客户端入参:
  *   obj01:
  *     使用HttpEntity封装,
  *     请求头(headers): HttpHeaders
  *     请求体(body): String类型的JSON字符串
  *   obj02:
  *     URL中使用占位符传参,String类型的JSON字符串
  * 客户端返回值: String类型
  */
 public static void f1_2() throws Exception {
  // 1.请求URL,带占位符
  String postUrl = "http://127.0.0.1:19091/server/rest/f1_2?&obj02={json}";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.postForObject(postUrl, entity, String.class, json);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.4 POST请求方式4(postForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.3处理POST请求
  * 入参obj01字符串
  * 入参obj02字符串
  */
 @PostMapping("/f1_3")
 public Object f1_3(String obj01, String obj02) {
  log.info("RestfulController->f1_3,接收参数,obj01 = " + obj01.toString());
  log.info("RestfulController->f1_3,接收参数,obj02 = " + obj02.toString());
  log.info("RestfulController->f1_3,处理业务.");
  log.info("RestfulController->f1_3,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1_3();
 }
  /**
  * 1.3 POST请求客户端
  * 服务端入参:
  *    obj01只传字符串,不能使用@RequestBody注解
  *    obj02只传字符串,不能使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForObject
  * 客户端入参:
  *     URL中使用占位符传参,使用Map传参
  * 客户端返回值: String类型
  */
 public static void f1_3() throws Exception {
  // 1.请求URL,带占位符
  String postUrl = "http://127.0.0.1:19091/server/rest/f1_3?&obj01={obj01Data}&obj02={obj02Data}";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  Map<String, String> para = new HashMap<>();
  para.put("obj01Data", json);
  para.put("obj02Data", "杭州,一个非常不错的城市.");
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.postForObject(postUrl, null, String.class, para);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.5 POST请求方式5(postForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.处理POST请求
  * 入参使用@RequestBody封装为对象
  */
 @PostMapping("/f1")
 public Object f1(@RequestBody Object obj) {
  log.info("RestfulController->f1,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f1,处理业务.");
  log.info("RestfulController->f1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1_4();
 }
  /**
  * 1.4 POST请求客户端
  * 服务端入参: 使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForObject
  * 客户端入参:
  *   使用HttpEntity封装,
  *   请求头(headers): HttpHeaders
  *   请求体(body): String类型的JSON字符串
  *   使用URI封装URL参数
  * 客户端返回值: String类型
  */
 public static void f1_4() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest/f1";
  URI uri = new URI(postUrl);
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.postForObject(uri, entity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.6 POST请求方式6(postForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.处理POST请求
  * 入参使用@RequestBody封装为对象
  */
 @PostMapping("/f1")
 public Object f1(@RequestBody Object obj) {
  log.info("RestfulController->f1,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f1,处理业务.");
  log.info("RestfulController->f1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1();
 }
 /**
  * 1.6 POST请求客户端
  * 服务端入参: 使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForObject
  * 客户端入参:
  *   使用HttpEntity封装,
  *   请求头(headers): HttpHeaders
  *   请求体(body): String类型的JSON字符串
  * 客户端返回值: 自定义对象ResultObj.class
  */
 public static void f1_6() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest/f1";
  // 2.请求参数JSON格式
  UserModel userModel = new UserModel();
  userModel.setUserName("HangZhou20220718");
  userModel.setTradeName("Vue进阶教程");
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<UserModel> entity = new HttpEntity<>(userModel, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  ResultObj resultData = restTemplate.postForObject(postUrl, entity, ResultObj.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.7 POST请求方式7(postForLocation)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.2处理POST请求
  * 入参使用@RequestBody封装为对象
  * 需注入HttpServletResponse和设置响应头
  */
 @PostMapping("/f1_uri")
 public Object f1_uri(@RequestBody Object obj) throws URISyntaxException {
  log.info("CommonController->f1_uri,接收参数,obj = " + obj.toString());
  log.info("CommonController->f1_uri,处理业务.");
  log.info("CommonController->f1_uri,返回.");
  // postForLocation返回值,不为空的话,必须设置响应头的Location属性
  response.setHeader("Location", "/server/work");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1_uri();
 }
   /**
  * POST请求客户端
  * 服务端入参: 使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForLocation
  * 客户端入参:
  *   使用HttpEntity封装,
  *   请求头(headers): HttpHeaders
  *   请求体(body): String类型的JSON字符串
  * 客户端返回值: URI对象
  */
 public static void f1_uri() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest/f1_uri";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  URI resultData = restTemplate.postForLocation(postUrl, entity);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.8 POST请求方式8(postForEntity)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.处理POST请求
  * 入参使用@RequestBody封装为对象
  */
 @PostMapping("/f1")
 public Object f1(@RequestBody Object obj) {
  log.info("RestfulController->f1,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f1,处理业务.");
  log.info("RestfulController->f1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1();
 }
 /**
  * 1.5 POST请求客户端
  * 服务端入参: 使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: postForEntity
  * 客户端入参:
  *   使用HttpEntity封装,
  *   请求头(headers): HttpHeaders
  *   请求体(body): String类型的JSON字符串
  * 客户端返回值: ResponseEntity
  *   功能: 便于获取HttpEntity的HttpHeaders信息
  */
 public static void f1_5() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest/f1";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  HttpEntity<String> entity = new HttpEntity<>(json, headers);
  // 5.使用RestTemplate发起请求与接收返回值
  ResponseEntity<String> resultData = restTemplate.postForEntity(postUrl, entity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

1.9 POST请求方式9(exchange)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 1.处理POST请求
  * 入参使用@RequestBody封装为对象
  */
 @PostMapping("/f1")
 public Object f1(@RequestBody Object obj) {
  log.info("RestfulController->f1,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f1,处理业务.");
  log.info("RestfulController->f1,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f1();
 }
 /**
  * 1.7 POST请求客户端
  * 服务端入参: 使用@RequestBody注解
  * 服务端返回值: 使用@ResponseBody注解的JavaBean对象
  * 客户端方法: exchange
  * 客户端入参:
  *   使用RequestEntity封装HttpEntity等等
  * 客户端返回值: ResponseEntity
  */
 public static void f1_7() throws Exception {
  // 1.请求URL
  String postUrl = "http://127.0.0.1:19091/server/rest/f1";
  // 2.请求参数JSON格式
  Map<String, String> map = new HashMap<>();
  map.put("userName", "HangZhou20220718");
  map.put("tradeName", "Vue进阶教程");
  String json = JSON.toJSONString(map);
  // 3.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 4.设置RestTemplate参数(请求头和body)
  HttpHeaders headers = new HttpHeaders();
  MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
  headers.setContentType(mediaType);
  headers.add("Accept", "application/json");
  URI uri = new URI(postUrl);
  RequestEntity<String> requestEntity = new RequestEntity<>(json, headers, HttpMethod.POST, uri);
  // 5.使用RestTemplate发起请求与接收返回值
  ResponseEntity<String> resultData = restTemplate.exchange(requestEntity, String.class);
  System.out.println("从服务端返回结果: " + resultData);
}}

2.GET请求

2.1 GET请求方式1(getForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 2.处理GET请求
  * 入参使用@RequestParam修饰
  */
 @GetMapping("/f2")
 public Object f2(@RequestParam("obj") String obj) {
  log.info("RestfulController->f2,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f2,处理业务.");
  log.info("RestfulController->f2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f2();
 }
 /**
  * 2.GET请求客户端
  * 服务端入参注解: @RequestParam
  * 客户端方法: getForObject
  */
 public static void f2() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest/f2";
  String obj = "Vue进阶教程";
  String para = "?obj=" + obj;
  getUrl = getUrl + para;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.getForObject(getUrl, String.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

2.2 GET请求方式2(getForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 2.处理GET请求
  * 入参使用@RequestParam修饰
  */
 @GetMapping("/f2")
 public Object f2(@RequestParam("obj") String obj) {
  log.info("RestfulController->f2,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f2,处理业务.");
  log.info("RestfulController->f2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f2_1();
 }
/**
  * 2.1 GET请求客户端
  * 服务端入参注解: @RequestParam
  * 客户端方法: getForObject
  * 客户端入参: 使用占位符和使用String类型传参
  */
 public static void f2_1() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest/f2?&obj={obj}";
  String obj = "Vue进阶教程";
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.getForObject(getUrl, String.class, obj);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

2.3 GET请求方式3(getForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 2.处理GET请求
  * 入参使用@RequestParam修饰
  */
 @GetMapping("/f2")
 public Object f2(@RequestParam("obj") String obj) {
  log.info("RestfulController->f2,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f2,处理业务.");
  log.info("RestfulController->f2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f2_2();
 }
 /**
  * 2.2 GET请求客户端
  * 服务端入参注解: @RequestParam
  * 客户端方法: getForObject
  * 客户端入参: 使用占位符和使用Map类型传参
  */
 public static void f2_2() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest/f2?&obj={obj}";
  String obj = "Vue进阶教程Map";
  Map<String, String> para = new HashMap<>();
  para.put("obj", obj);
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.getForObject(getUrl, String.class, obj);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

2.4 GET请求方式4(getForObject)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 3.处理GET请求
  * 入参使用@PathVariable修饰
  */
 @GetMapping("/f3/{obj}")
 public Object f3(@PathVariable("obj") String obj) {
  log.info("RestfulController->f3,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f3,处理业务.");
  log.info("RestfulController->f3,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f3();
 }
 /**
  * 3.使用RestTemplate调用服务端的GET请求
  * 服务端入参注解: @PathVariable
  */
 public static void f3() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest/f3/";
  String obj = "Vue进阶教程";
  getUrl = getUrl + obj;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  String resultData = restTemplate.getForObject(getUrl, String.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

2.5 GET请求方式5(getForEntity)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 2.处理GET请求
  * 入参使用@RequestParam修饰
  */
 @GetMapping("/f2")
 public Object f2(@RequestParam("obj") String obj) {
  log.info("RestfulController->f2,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f2,处理业务.");
  log.info("RestfulController->f2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f2_3();
 }
 /**
  * 2.3 GET请求客户端
  * 服务端入参注解: @RequestParam
  * 客户端使用方法: getForEntity
  * 客户端返回值: ResponseEntity
  */
 public static void f2_3() throws Exception {
  // 1.请求URL与组装请求参数
  String getUrl = "http://127.0.0.1:19091/server/rest/f2";
  String obj = "Vue进阶教程";
  String para = "?obj=" + obj;
  getUrl = getUrl + para;
  // 2.创建RestTemplate
  RestTemplate restTemplate = new RestTemplate();
  // 3.使用RestTemplate发起请求与接收返回值
  ResponseEntity<String> resultData = restTemplate.getForEntity(getUrl, String.class);
  System.out.println("从服务端返回结果: " + resultData);
 }
}

2.6 GET请求方式6(exchange)

/**
 * 服务端类
 */
@Slf4j
@RestController
@RequestMapping(value = "/rest")
public class RestfulController {
 /**
  * 2.处理GET请求
  * 入参使用@RequestParam修饰
  */
 @GetMapping("/f2")
 public Object f2(@RequestParam("obj") String obj) {
  log.info("RestfulController->f2,接收参数,obj = " + obj.toString());
  log.info("RestfulController->f2,处理业务.");
  log.info("RestfulController->f2,返回.");
  return ResultObj.builder().code("200").message("成功").build();
 }
}

/**
 * 客户端类
 */
public class RestUtils {
 public static void main(String[] args) throws Exception {
   f2_4();
 }
 /**
  * 2.4 GET请求客户端
  * 服务端入参注解: @RequestParam
  * 客户端方法: exchange
  */
 public static void f2_4() throws Exception {
   // 1.请求URL与组装请求参数
   String getUrl = "http://127.0.0.1:19091/server/rest/f2";
   String obj = "Vue进阶教程";
   String para = "?obj=" + obj;
   getUrl = getUrl + para;
   // 2.创建RestTemplate
   RestTemplate restTemplate = new RestTemplate();
   // 3.使用RestTemplate发起请求与接收返回值
   ResponseEntity<String> resultData = restTemplate.exchange(getUrl,
           HttpMethod.GET, null, String.class);
   System.out.println("从服务端返回结果: " + resultData);
 }
}

四、RestTemplate源码封装逻辑

本例以postForObject为例。

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

1.创建RestTemplate对象

创建RestTemplate对象,即初始化实例。

(1)加载响应错误处理器,即DefaultResponseErrorHandler。

(2)加载响应头部抽取器,即HeadersExtractor。

(3)加载一系列的http消息转换器,即HttpMessageConverter接口的各种实现类。

(4)初始化URI末班处理器。

RestTemplate restTemplate = new RestTemplate();
public RestTemplate() {
  this.messageConverters = new ArrayList();
  this.errorHandler = new DefaultResponseErrorHandler();
  this.headersExtractor = new RestTemplate.HeadersExtractor();
  this.messageConverters.add(new ByteArrayHttpMessageConverter());
  this.messageConverters.add(new StringHttpMessageConverter());
  this.messageConverters.add(new ResourceHttpMessageConverter(false));
  if (!shouldIgnoreXml) {
      try {
          this.messageConverters.add(new SourceHttpMessageConverter());
      } catch (Error var2) {
      }
  }
  this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
  if (romePresent) {
      this.messageConverters.add(new AtomFeedHttpMessageConverter());
      this.messageConverters.add(new RssChannelHttpMessageConverter());
  }
  if (!shouldIgnoreXml) {
      if (jackson2XmlPresent) {
          this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
      } else if (jaxb2Present) {
          this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
      }
  }
  if (jackson2Present) {
      this.messageConverters.add(new MappingJackson2HttpMessageConverter());
  } else if (gsonPresent) {
      this.messageConverters.add(new GsonHttpMessageConverter());
  } else if (jsonbPresent) {
      this.messageConverters.add(new JsonbHttpMessageConverter());
  } else if (kotlinSerializationJsonPresent) {
      this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
  }
  if (jackson2SmilePresent) {
      this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
  }
  if (jackson2CborPresent) {
      this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
  }
  this.uriTemplateHandler = initUriTemplateHandler();
}

2.调用postForObject

触发调用postForObject。

(1)设置请求回调信息,即RequestCallback。

(2)设置http消息转换抽取器,即HttpMessageConverterExtractor。

(3)触发执行器调用,即execute。

@Nullable
public <T> T postForObject(String url, @Nullable Object request, 
    Class<T> responseType, Object... uriVariables) throws RestClientException {
  RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
  HttpMessageConverterExtractor<T> responseExtractor = 
  new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
  return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);
}

3.调用execute

(1)获取URI信息

(2)触发调用doExecute,这是一个protected方法。

@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
    URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);
    return this.doExecute(expanded, method, requestCallback, responseExtractor);
}

4.调用doExecute

在RestTemplate中,doExecute是具体执行逻辑。

(1)创建ClientHttpRequest。

(2)调用ClientHttpRequest的execute具体执行。

(3)解析ClientHttpRequest的execute执行返回的ClientHttpResponse

(4)响应抽取器从ClientHttpResponse解析具体数据。

(5)在finally中关闭ClientHttpResponse数据流。

@Nullable
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
 Assert.notNull(url, "URI is required");
 Assert.notNull(method, "HttpMethod is required");
 ClientHttpResponse response = null;
 Object var14;
 try {
    ClientHttpRequest request = this.createRequest(url, method);
    if (requestCallback != null) {
        requestCallback.doWithRequest(request);
    }
    response = request.execute();
    this.handleResponse(url, method, response);
    var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;
 } catch (IOException var12) {
    String resource = url.toString();
    String query = url.getRawQuery();
    resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;
    throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);
 } finally {
    if (response != null) {
        response.close();
    }
 }
 return var14;
}

以上,感谢。

2022年7月22日