目录
- 1.需求说明
- 2.项目环境搭建
- 3.代码实现
- 3.1.使用 RestTemplate 进行调用
- 3.1.1.项目 A
- 3.1.2.项目 B
- 3.2.测试
- 3.3.使用 JsonObject 来传递和接收 json 数据
- 3.3.1.说明
- 3.3.2.代码实现
- 3.4.其它说明
- 3.4.1.restTemplate.exchange()
- 3.4.2.restTemplate.postForObject()
- 3.4.3.区别总结
1.需求说明
现在项目 A 需要通过调用项目 B 中的接口(传递的信息有员工 id 和员工姓名)来获得某一员工的其它信息,现在要使用 RestTemplate 来完成这一跨项目接口调用。
注:项目 A 和项目 B 并未在同一个 Spring Cloud 或类似微服务框架中,因此这里暂不考虑使用
Feign
来进行服务调用。
2.项目环境搭建
(1)在 IDEA 中创建两个 Spring Boot 项目(分别称为项目 A 和项目 B),具体可以参考【环境搭建】使用IDEA创建SpringBoot项目详细步骤这篇文章。
(2)项目 A 的配置文件 application.yml
中的内容如下:
server:port: 8080rpc:# 项目 B 的接口地址url: http://localhost:8081/employ/info
(3)项目 B 的配置文件 application.yml
中的内容如下:
server:port: 8081
为了方便,本文创建的两个项目都是在本地运行的,因此它们的端口号不能一样。
3.代码实现
3.1.使用 RestTemplate 进行调用
(1)RestTemplate
是一个用于访问 RESTful 服务的 Spring Framework 类。它基于 HTTP 协议,可以进行 GET、POST、PUT、DELETE 等 HTTP 操作,用于向远程服务器发送请求并处理响应。因此本文选择使用 RestTemplate 来进行接口调用。
(2)RestTemplate 的详细信息见官网文档。
3.1.1.项目 A
EmployeeEntity.java
import lombok.Data;@Data
public class EmployeeEntity {private String id;private String name;private String posName;private String jobLevelName;private String departmentName;
}
RPCController.java
import com.example.htmltopdf.domain.EmployeeEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;import java.util.Collections;@Slf4j
@RestController
@RequestMapping("/rpc")
public class RPCController {@Value("${rpc.url}")private String URL;@Autowiredprivate RestTemplate restTemplate;/*** @description: 模拟通过调用项目 B 的接口来根据员工 id 和 name 获取员工的其它信息* @param employeeEntity 员工信息,只包含 id 和 name* @return: 员工信息* */@PostMapping()public EmployeeEntity getEmpInfo(EmployeeEntity employeeEntity) {//设置请求头,特别是 Content-Type 和 Accept 头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));//设置请求体,这里是将员工 id 和员工 name 封装到 EmployeeEntity 对象中HttpEntity<EmployeeEntity> requestEntity = new HttpEntity<>(employeeEntity, headers);//发送 POST 请求,并接收返回的 JSON 结果EmployeeEntity result = restTemplate.postForObject(URL, requestEntity, EmployeeEntity.class);assert result != null;log.info(result.toString());return result;}
}
3.1.2.项目 B
EmployeeEntity.java
//代码同上
EmployeeController.java
import com.example.oss.domain.EmployeeEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/employ")
public class EmployeeController {@PostMapping("/info")public EmployeeEntity getEmployeeInfo(@RequestBody EmployeeEntity employeeEntity) {//根据项目 A 传过来的 employeeEntity 进行相关操作,下面就直接设置了,并没有真的去数据库中查找employeeEntity.setPosName("软件开发工程师");employeeEntity.setJobLevelName("高级");employeeEntity.setDepartmentName("软件开发部");return employeeEntity;}
}
3.2.测试
启动项目 A 和 B 后,在 Postman 中进行接口测试(注意是 POST 请求):
http://localhost:8080/rpc
3.3.使用 JsonObject 来传递和接收 json 数据
3.3.1.说明
(1)通过上面的代码可知,项目 A 在向项目 B 发送 Post 请求时,将请求体中的信息(员工 id 和员工 name)封装到 EmployeeEntity
对象中,而此时项目 B 中的接口也需要用相同的类对象来进行接收(如果通过 id 和 name 来接收会接收不到)。为了提高接口调用时传递和接收 json 数据的灵活性,我们可以考虑使用 JsonObject
。
(2)JsonObject 是指在 Java 中用来表示 JSON 对象的类或数据结构。它通常是指在 JSON 解析过程中,将 JSON 字符串解析为 Java 对象的一种表示形式。具体来说:
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它以键值对的形式组织数据,并使用逗号分隔,大括号
{}
包裹对象,方括号[]
包裹数组。 - JsonObject 是 Gson、Jackson 等库在 Java 中提供的类,用来表示一个 JSON 对象。它可以包含各种类型的数据:字符串、数字、布尔值、数组、甚至嵌套的对象。
- 在 Java 中使用 JsonObject 可以方便地解析、操作和生成 JSON 数据。例如,当从 HTTP 请求中接收到 JSON 数据时,可以使用 JsonObject 将其解析为 Java 对象,或者在构建 HTTP 响应时,将 Java 对象转换为 JSON 字符串格式。
3.3.2.代码实现
(1)在项目 A 和项目 B 的 pom.xml
文件中引入如下依赖:
<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.8</version>
</dependency>
(2)在项目 A 的配置文件 application.yml
中添加第二种方式的 url:
server:port: 8080rpc:url: http://localhost:8081/employ/infourl2: http://localhost:8081/employ/info/jsonobject
(3)项目 A 的 RPCController.java中添加如下代码:
@Value("${rpc.url2}")
private String URL2;/*** @description: 模拟通过调用项目 B 的接口来根据员工 id 和 name 获取员工的其它信息* @param id 员工 id* @param name 员工姓名* @return: 员工信息* */
@PostMapping("/jsonobject")
public String getEmpInfoByJsonObject(String id, String name) {//设置请求头,特别是 Content-Type 和 Accept 头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));//构建 JsonObject 对象JsonObject jsonObject = new JsonObject();jsonObject.addProperty("id", id);jsonObject.addProperty("name", name);//设置请求体,即要发送的员工信息 JSON 字符串HttpEntity<String> requestEntity = new HttpEntity<>(jsonObject.toString(), headers);//发送 POST 请求,并接收返回的 JSON 结果ResponseEntity<String> responseEntity = restTemplate.exchange(URL2, HttpMethod.POST, requestEntity, String.class);//获取响应体return responseEntity.getBody();
}
(4)项目 B 的 EmployeeController.java中添加如下代码:
@PostMapping("/info/jsonobject")
public ResponseEntity<String> getEmpInfoByJsonObject(@RequestBody String requestBody) {//使用 Gson 解析 JSON 字符串为 JsonObjectJsonObject jsonObject = new Gson().fromJson(requestBody, JsonObject.class);//从 JsonObject 中获取需要的员工信息String id = jsonObject.get("id").getAsString();String name = jsonObject.get("name").getAsString();//构建返回的 JSON 字符串JsonObject responseJson = new JsonObject();responseJson.addProperty("id", id);responseJson.addProperty("name", name);responseJson.addProperty("posName", "软件开发工程师2");responseJson.addProperty("jobLevelName", "高级2");responseJson.addProperty("departmentName", "软件开发部2");//返回 JSON 格式的响应return new ResponseEntity<>(responseJson.toString(), HttpStatus.OK);
}
(5)测试:启动项目 A 和 B 后,在 Postman 中进行接口测试(注意是 POST 请求):
http://localhost:8080/rpc/jsonobject
3.4.其它说明
RestTemplate
是 Spring Framework 提供的一个用于访问 RESTful 服务的模板类,它提供了多种方法来发送 HTTP 请求并处理响应。其中涉及到的两个方法 exchange()
和 postForObject()
在功能和使用上有一些区别:
3.4.1.restTemplate.exchange()
(1)exchange()
方法是 RestTemplate
提供的通用方法,用于执行 HTTP 请求并返回 ResponseEntity 对象。它支持所有 HTTP 方法(GET、POST、PUT、DELETE 等),并允许指定请求的 URL、HTTP 方法、请求头、请求体和响应类型等。主要特点包括:
- 通用性:支持所有的 HTTP 方法。
- 返回类型:返回
ResponseEntity<T>
,其中T
是请求返回的对象类型。 - 参数:可以设置请求的 URL、HTTP 方法、请求体、请求头等。
- 灵活性:可以处理各种复杂的 HTTP 请求和响应情况。
(2)使用示例:
ResponseEntity<User> response = restTemplate.exchange("http://api.example.com/users/{id}",HttpMethod.GET,null,User.class,1);
User user = response.getBody();
3.4.2.restTemplate.postForObject()
(1)postForObject()
方法是 RestTemplate
提供的简化方法,专门用于发送 HTTP POST 请求并返回结果对象。它适用于那些只需要发送 POST 请求并直接获得返回结果的场景。主要特点包括:
- HTTP 方法:固定为 POST 方法。
- 返回类型:直接返回请求的对象类型,而不是
ResponseEntity
。 - 参数:可以设置请求的 URL、请求体和返回对象的类型。
(2)使用示例:
User newUser = new User("John", 30);
User createdUser = restTemplate.postForObject("http://api.example.com/users",newUser,User.class);
在这个示例中,postForObject()
方法发送了一个 POST 请求到 http://api.example.com/users
,并将 newUser
对象作为请求体发送,期望返回一个 User
类型的对象作为响应结果。
3.4.3.区别总结
- 功能:
exchange()
更通用,支持所有 HTTP 方法;postForObject()
专门用于发送 POST 请求。 - 返回类型:
exchange()
返回ResponseEntity<T>
,可以获取完整的 HTTP 响应信息;postForObject()
直接返回请求的对象类型,简化了结果处理。 - 使用场景:如果需要更多的 HTTP 控制和灵活性,或者处理非 POST 请求,可以使用
exchange()
;如果只需简单地发送 POST 请求并获得结果对象,可以使用postForObject()
。
根据具体的需求和场景选择合适的方法来使用
RestTemplate
,可以更高效地与 RESTful 服务进行交互。