记录:393
场景:在Spring Cloud微服务架构中,使用nacos注册和配置微服务,使用RestTemplate客户端调用微服务发布的Restful接口。
版本:JDK 1.8,SpringBoot 2.6.3,springCloud 2021.0.1,Nacos 2.1.1。
3.1初始化准备
3.1.1创建Maven工程
使用IntelliJ IDEA创建Maven工程。
(1)微服务名称
名称:hub-example-303-resttemplate
(2)微服务groupId和artifactId
groupId: com.hub
artifactId: hub-example-303-resttemplate
(3)微服务核心模块版本
spring-boot 2.6.3
spring-cloud 2021.0.1
spring-cloud-alibaba 2021.0.1.0
3.1.2准备nacos
Nacos版本:Nacos 2.1.1。
(1)启动和登录nacos
启动命令:sh startup.sh -m standalone
地址:http://127.0.0.1:8848/nacos
用户名/口令:nacos/nacos
(2)创建命名空间
命名空间ID:aa3eebb6-daa2-4db8-9a29-03dd8a17db15
命名空间名:hub
3.2修改pom.xml
修改pom.xml,引入项目依赖Jar和管理Jar包。
3.2.1修改pom.xml文件
(1)RestTemplate依赖
org.springframework.web.client.RestTemplate,在spring-web-5.3.15.jar中。引入以下依赖就自动导入了。
org.springframework.boot
spring-boot-starter-web
(2)RestTemplate依赖
使用RestTemplate调用微服务时,且微服务注册在Nacos时,需引入客户端负载均衡包。
org.springframework.cloud
spring-cloud-starter-loadbalancer
3.2.2全量pom.xml文件
全量pom.xml文件请参考附录:3.10.1全量pom.xml文件
3.3创建bootstrap.yml文件和配置nacos
3.3.1创建bootstrap.yml
server:
port: 18303
servlet:
context-path: /hub-303-rest
spring:
application:
name: hub-example-303-resttemplate
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:18848
username: nacos
password: nacos
namespace: aa3eebb6-daa2-4db8-9a29-03dd8a17db15
group: DEFAULT_GROUP
config:
server-addr: 127.0.0.1:18848
username: nacos
password: nacos
namespace: aa3eebb6-daa2-4db8-9a29-03dd8a17db15
group: DEFAULT_GROUP
file-extension: yaml
shared-configs:
- dataId: hub-example01-config.yml
group: DEFAULT_GROUP
refresh: true
3.4创建启动类
3.4.1创建包
com.hub.example.domain:微服务使用到的DTO等实体类。
com.hub.example.controller:Controller类,发布Restful接口。
com.hub.example.config:配置类。
3.4.2启动类
包名:com.hub.example。
启动类:HubExampleFeignApplication。
(1)内容
@SpringBootApplication
@ComponentScan(basePackages = "com.hub.example.*")
@EnableDiscoveryClient
public class HubExampleRestApplication {
public static void main(String[] args) {
SpringApplication.run(HubExampleRestApplication.class, args);
}
}
(2)解析
@SpringBootApplication,SpringBoot标记启动类的注解。
@ComponentScan,扫描指定的包,将组件加载到IOC容器中。
@EnableDiscoveryClient,开启服务发现功能。
3.5创建配置
3.5.1配置类
@Configuration
public class RestTemplateConfiguration {
@Bean(name = "msRestTemplate")
@Primary
@LoadBalanced
public RestTemplate msRestTemplate() {
return new RestTemplate();
}
}
3.5.2解析
使用RestTemplate调用注册到Nacos的微服务时,需加上@LoadBalanced注解,启动客户端负载均衡,否则会报错。
3.6编写Controller代码
3.6.1Controller代码
@RestController
@RequestMapping("/hub/example/city")
@RefreshScope
@Slf4j
public class CityController {
@Qualifier("msRestTemplate")
@Autowired
private RestTemplate msRestTemplate;
@PostMapping("/queryCityByCityId")
public ResultObj queryCityByCityId(String cityId) {
// 1.组装请求头
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("cityNo","0517");
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
// 2.组装请求实体
HttpEntity httpEntity = new HttpEntity<>(cityId,httpHeaders);
String url="http://hub-example-301-nacos/hub-301-nacos/hub/example/city/queryCityByCityId";
ResponseEntity responseEntity = msRestTemplate.postForEntity(url,httpEntity,String.class,new Object[0]);
// 3.解析应答实体
String result = responseEntity.getBody();
ResultObj resultObj= JSONUtil.toBean(result,ResultObj.class);
CityDTO cityDTO =JSONUtil.toBean((JSONObject) resultObj.getData(),CityDTO.class);
return ResultObj.data(200, cityDTO, "执行成功");
}
@PostMapping("/queryCityByCity")
public ResultObj queryCityByCity(@RequestBody CityReqDTO cityReqDTO) {
// 1.组装请求头
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("cityNo","0517");
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
// 2.组装请求实体
HttpEntity httpEntity = new HttpEntity<>(cityReqDTO,httpHeaders);
String url="http://hub-example-301-nacos/hub-301-nacos/hub/example/city/queryCityByCity";
ResponseEntity responseEntity = msRestTemplate.postForEntity(url,httpEntity,CityDTO.class,new Object[0]);
// 3.解析应答实体
CityDTO cityDTO = responseEntity.getBody();
return ResultObj.data(200, cityDTO, "执行成功");
}
}
3.6.2解析RestTemplate调用远程微服务
(1)调用方式
String url="http://hub-example-301-nacos/hub-301-nacos/hub/example/city/queryCityByCity";
ResponseEntity responseEntity = msRestTemplate.postForEntity(url,httpEntity,CityDTO.class,new Object[0]);
(2)解析
在url中,hub-example-301-nacos,是目标微服务的名称,即微服务注册在Nacos中名称。
/hub-301-nacos,是目标微服务配置的server.servlet.context-path属性。
/hub/example/city/queryCityByCity,是目标微服务的Controller路径:@RequestMapping("/hub/example/city");和方法上的请求路径:@PostMapping("/queryCityByCity")。
3.6.3解析请求实体和响应实体
org.springframework.web.client.RestTemplate,操作http请求的客户端。
org.springframework.util.MultiValueMap,存储请求头的key、value键值对。
org.springframework.http.HttpHeaders,http请求头。
org.springframework.http.HttpEntity,http请求实体。
org.springframework.http.ResponseEntity,http响应实体。
在HttpHeaders中的核心属性:
final MultiValueMap headers;
在HttpEntity中的核心属性:
private final HttpHeaders headers;
private final T body;
在HttpEntity中的核心属性:
ResponseEntity中的核心属性(其中headers和body从HttpEntity中继承):
private final Object status;
private final HttpHeaders headers;
private final T body;
3.6.4使用RestTemplate传递请求头信息
使用RestTemplate传递请求头信息。
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("cityNo","0517");
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
3.7支撑对象
3.7.1CityDTO
@Data
public class CityDTO implements Serializable {
private Long cityId;
private String cityName;
private Double landArea;
private Long population;
private Double gross;
private String cityDescribe;
private String dataYear;
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss"
)
private Date updateTime;
}
3.7.2ResultObj
@Data
public class ResultObj implements Serializable {
private int code;
private boolean success;
private String msg;
private T data;
private ResultObj(int code, T data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
this.success = code == 200;
}
public static ResultObj data(int code, T data, String msg) {
return new ResultObj<>(code, data, msg);
}
}
3.7.3CityReqDTO
@Data
public class CityReqDTO {
private Long cityId;
private String cityName;
}
3.8目标微服务信息
使用RestTemplate调用的远程微服务信息。
3.8.1目标微服名称
微服务名:hub-example-301-nacos
3.8.2目标微服Controller
@RestController
@RequestMapping("/hub/example/city")
@RefreshScope
@Slf4j
public class CityController {
@Autowired
private HttpServletRequest request;
@PostMapping("/queryCityByCityId")
public ResultObj queryCityByCityId(String cityId) {
log.info("cityNo = " + request.getHeader("cityNo"));
CityDTO cityDTO = new CityDTO();
cityDTO.setCityId(cityId != null ? Long.parseLong(cityId) : 1L);
cityDTO.setCityName(cityName);
cityDTO.setUpdateTime(new Date());
return ResultObj.data(200, cityDTO, "执行成功");
}
@PostMapping("/queryCityByCity")
public CityDTO queryCityByCity(@RequestBody CityReqDTO cityReqDTO) {
CityDTO cityDTO = new CityDTO();
cityDTO.setCityId(cityReqDTO.getCityId());
cityDTO.setCityName(cityReqDTO.getCityName());
cityDTO.setCityDescribe(cityReqDTO.getCityName() + "是一个互联网城市.");
cityDTO.setUpdateTime(new Date());
return cityDTO;
}
}
3.9使用Postman工具测试
使用Postman工具测试。
测试地址:http://127.0.0.1:18302/hub-302-feign/hub/example/city/queryCityByCity
测试入参:
{
"cityId":"20230326",
"cityName":"杭州"
}
返回结果:
{
"code": 200,
"success": true,
"msg": "执行成功",
"data": {
"cityId": 20230326,
"cityName": "杭州",
"landArea": null,
"population": null,
"gross": null,
"cityDescribe": "杭州是一个互联网城市.",
"dataYear": null,
"updateTime": "2023-03-26 21:16:55"
}
}
3.10附录
3.10.1全量pom.xml文件
4.0.0
com.hub
hub-example-303-resttemplate
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.6.3
应用RestTemplate调用微服务
jar
1.8
1.8
UTF-8
UTF-8
2.6.3
2.6.3
2021.0.1
2021.0.1.0
2.1.1
1.18.24
30.1-jre
5.8.12
org.springframework.boot
spring-boot-starter-parent
${spring.boot.version}
pom
import
org.springframework.cloud
spring-cloud-dependencies
${spring.cloud.version}
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring.cloud.alibaba.version}
pom
import
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-bootstrap
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.cloud
spring-cloud-starter-loadbalancer
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
com.alibaba.nacos
nacos-client
com.alibaba.nacos
nacos-client
${nacos.client.version}
org.projectlombok
lombok
${lombok.version}
com.google.guava
guava
${guava.version}
cn.hutool
hutool-all
${hutool.version}
${project.artifactId}
org.springframework.boot
spring-boot-maven-plugin
${spring.boot.maven.plugin.version}
true
true
repackage
以上,感谢。
2023年3月26日