1 Spring Cloud简介
1.1 简介
Spring Cloud项目的官方网址:https://projects.spring.io/spring-cloud/
Spring Cloud并不是一个项目,而是一组项目的集合.在Spring Cloud中包含了很多的子项目.每一个子项目都是一种微服务开发过程中遇到的问题的一种解决方案.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
1.2 子项目介绍
子项目名称 |
描述 |
Spring CloudAws |
用于简化整合Amazon Web Service的组件 |
Spring Cloud Bus |
事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与Spring Cloud Config联合实现热部署。 |
Spring CloudCli |
基于 Spring Boot CLI,可以让你以命令行方式快速建立云组件。 |
Spring CloudCommons |
服务发现、负载均衡、熔断机制这种模式为Spring Cloud客户端提供了一个通用的抽象层。 |
Spring Cloud Config |
配置管理开发工具包,可以让你把配置放到远程服务器,目前支持本地存储、Git以及Subversion。 |
Spring CloudContract |
|
Spring Cloud Netflix |
针对多种Netflix组件提供的开发工具包,其中包括Eureka、Hystrix、Zuul、Archaius等。 |
Spring CloudSecurity |
安全工具包 |
Spring CloudCloudfoundry |
通过Oauth2协议绑定服务到CloudFoundry,CloudFoundry是VMware推出的开源PaaS云平台 |
Spring CloudConsul |
封装了Consul操作,consul是一个服务发现与配置工具,与Docker容器可以无缝集成。 |
Spring Cloud Sleuth |
日志收集工具包,封装了Dapper,Zipkin和HTrace操作.Spring Cloud应用的分布式跟踪实现 |
Spring Cloud Stream |
数据流操作开发包,封装了与Redis,Rabbit、Kafka等发送接收消息,实现的消息微服务。 |
Spring CloudZookeeper |
基于ZooKeeper的服务发现与配置管理组件 |
Spring Boot |
|
Spring CloudTask |
用于快速构建数据处理的应用 |
Spring CloudGateway |
Spring Cloud网关相关的整合实现 |
1.3 Spring Cloud的版本介绍
当我们通过搜索引擎查找一些Spring Cloud的文章或者示例的时候,往往可以在依赖中看到很多不同版本的名字, 比如: Angel.SR6, Brixton.SR5等.那么为什么Spring Cloud没有像其他的Spring的项目使用类似1.x.x版本命名规则呢?
由于Spring Cloud不像Spring社区其他项目那样相对独立,它是拥有诸多子项目的大型综合项目.可以说是对微服务架构解决方案的综合套件的组合,起包含的各个子项目也都是进行独立的更新和迭代,各自都维护自己的发布版本号.因此每一个Spring Cloud的版本都会包含多个不同版本的子项目,为了管理每一个版本的子项目清单,避免Spring Cloud的版本号与其子项目的版本号相混淆,没有采用版本号的方式,而是通过命名的方式.
我们也可以在spring的官网上查看到对应的最新稳定版本信息: https://projects.spring.io/spring-cloud/
并且也可以看到最新Edgware.SR4稳定版对应的子项目的各个版本号
关于Spring Cloud的历史版本信息我们可以在github上查看到: https://github.com/spring-cloud/spring-cloud-release/releases
我们本次讲解的是最新的稳定版本Edgware.SR4 , 是基于Spring Boot 1.5.14.RELEASE版本实现的.
2 Spring Boot实现微服务
在正式学习Spring Cloud之前我们先使用Spring Boot实现一个微服务。
业务非常简单:
1、 商品微服务:通过商品id查询商品的服务;
2、 订单微服务:通过订单id查询订单数据,同时需要调用商品微服务查询出订单详情数据对应的商品数据
说明:
1、 对于商品微服务而言,商品微服务是服务的提供者,订单微服务是服务的消费者;
2、 对于订单微服务而言,订单微服务是服务的提供者,人是服务的消费者。
2.1 实现商品微服务
2.1.1 pom.xml文件的配置
<projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.microservice</groupId> <artifactId>itcast-micorservice-item</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 定义变量 --> <properties> <java.version>1.8</java.version> </properties>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <dependencies> <!-- 加入web的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
2.1.2 创建实体Item
package cn.itcast.microservice.pojo;
publicclass Item { private Long id; // 唯一标识 private String title; // 商品标题 private String pic; // 图片的pic地址 private String desc; // 描述信息 private Long price; // 价格 }
2.1.3 编写ItemService
package cn.itcast.microservice.service; import java.util.HashMap; import java.util.Map; importorg.springframework.stereotype.Service; import cn.itcast.microservice.pojo.Item; @Service publicclass ItemService { privatestaticfinal Map<Long, Item>MAP = new HashMap<Long, Item>(); static { // 准备一些静态数据 MAP.put(1L, new Item(1L, "商品标题1", "http://图片1", "商品描述1", 1000L)); MAP.put(2L, new Item(1L, "商品标题2", "http://图片2", "商品描述2", 2000L)); MAP.put(3L, new Item(1L, "商品标题3", "http://图片3", "商品描述3", 3000L)); MAP.put(4L, new Item(1L, "商品标题4", "http://图片4", "商品描述4", 4000L)); MAP.put(5L, new Item(1L, "商品标题5", "http://图片5", "商品描述5", 5000L)); MAP.put(6L, new Item(1L, "商品标题6", "http://图片6", "商品描述6", 6000L)); MAP.put(7L, new Item(1L, "商品标题7", "http://图片7", "商品描述7", 7000L)); MAP.put(8L, new Item(1L, "商品标题8", "http://图片8", "商品描述8", 8000L)); } /** * 模拟实现商品查询 * * @param id * @return */ public Item queryItemById(Long id) { returnMAP.get(id); } }
2.1.4 编写ItemController
package cn.itcast.microservice.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.GetMapping; importorg.springframework.web.bind.annotation.RestController; import cn.itcast.microservice.pojo.Item; import cn.itcast.microservice.service.ItemService; @RestController publicclass ItemController { @Autowired private ItemService itemService; /** * 对外提供接口服务,查询商品信息 * * @param id * @return */ @GetMapping(value = "/item/{id}") public Item queryItemById(@PathVariable("id") Long id) { returnthis.itemService.queryItemById(id); } }
2.1.5 程序入口
package cn.itcast.microservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication//声明这是一个Spring Boot项目 publicclassItemApplication { publicstaticvoid main(String[] args) { SpringApplication.run(ItemApplication.class, args); } }
2.1.6 创建配置文件
在src/main/resources目录下创建一个application.properties配置文件,在该文件中可以配置如下内容:
server.port=8081
指定服务启动占用的端口
2.1.7 启动项目进行访问
2.2 实现订单微服务
2.2.1 pom.xml文件的配置
<projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.microservice</groupId> <artifactId>itcast-microservice-order</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 定义变量 --> <properties> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <dependencies> <!-- 加入web的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
2.2.2 创建实体Order
package cn.itcast.microservice.pojo; import java.util.Date; import java.util.List; publicclassOrder {
privateStringorderId; // 订单的id privateLonguserId; // 用户id privateDatecreateDate; // 创建时间 privateDateupdateDate; // 修改时间 privateList<OrderDetail>orderDetails; // 订单详情 }
2.2.3 创建实体OrderDetail
package cn.itcast.microservice.pojo; publicclassOrderDetail { privateStringorderId ; // 订单id privateItemitem ; // 商品 }
2.2.4 复制Item实体
2.2.5 编写OrderService
该Service实现的根据订单Id查询订单的服务,为了方便测试,我们将构造数据实现,不采用查询数据库的方式。
package cn.itcast.microservice.service; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; import cn.itcast.microservice.pojo.Item; import cn.itcast.microservice.pojo.Order; import cn.itcast.microservice.pojo.OrderDetail; @Service public class OrderService { private static final Map<String, Order> MAP = new HashMap<String, Order>(); static { // 构造测试数据 Order order = new Order(); order.setOrderId("59193738268961441"); order.setCreateDate(new Date()); order.setUpdateDate(order.getCreateDate()); order.setUserId(1L); // 创建OrderDetail集合对象 List<OrderDetail> orderDetails = new ArrayList<OrderDetail>(); Item item = new Item(); // 此处并没有商品的数据,需要调用商品微服务获取 item.setId(1L); orderDetails.add(new OrderDetail(order.getOrderId(), item)); item = new Item(); // 构造第二个商品数据 item.setId(2L); orderDetails.add(new OrderDetail(order.getOrderId(), item)); // 将OrderDetail数据集设置给Order对象 order.setOrderDetails(orderDetails); // 将Order对象添加到Map中 MAP.put(order.getOrderId(), order); } /** * 根据订单id查询订单数据 * * @param orderId * @return */ public Order queryOrderById(String orderId) { Order order = MAP.get(orderId); // 获取Order中的OrderDetail列表数据,然后遍历集合获取每一个OrderDetail,然后调用商品微服务根据商品的id查询商品数据 return order; } }
2.2.6 实现ItemService
package cn.itcast.microservice.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import cn.itcast.microservice.pojo.Item; @Service publicclassItemService { @Autowired privateRestTemplaterestTemplate ; /** * 根据商品的id进行查询 * @param id * @return */ publicItem queryById(Longid) { // 使用HttpClient工具发送请求获取商品的数据 // 我们也可以使用spring给我们提供的另个一个类RestTemplate,来发送Http请求 Itemitem = restTemplate.getForObject("http://localhost:8081/item/" + id, Item.class) ; // 返回 returnitem ; } }
2.2.7 完善OrderService
@Autowired privateItemServiceitemService ; /** * 根据订单id查询订单数据 * * @param orderId * @return */ publicOrder queryOrderById(StringorderId) { Orderorder = MAP.get(orderId); // 获取Order中的OrderDetail列表数据,然后遍历集合获取每一个OrderDetail,然后调用商品微服务根据商品的id查询商品数据 for (OrderDetailorderDetail : order.getOrderDetails()) { Itemitem = itemService.queryById(orderDetail.getItem().getId()) ; orderDetail.setItem(item); } returnorder; }
2.2.8 编写OrderController
package cn.itcast.microservice.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import cn.itcast.microservice.pojo.Order; import cn.itcast.microservice.service.OrderService; @RestController public class OrderController {
@Autowired private OrderService orderService; @GetMapping(value = "/order/{orderId}") public Order queryOrderById(@PathVariable("orderId") String orderId) { return this.orderService.queryOrderById(orderId); } }
2.2.9 编写启动类
package cn.itcast.microservice;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication publicclassOrderApplication {
@Bean public RestTemplate restTemplate() { return new RestTemplate(); } // 程序入口 publicstaticvoid main(String[] args) { /** * 启动程序 */ SpringApplication.run(OrderApplication.class, args) ; } }
2.2.10 创建配置文件
在src/main/resources目录下创建一个application.properties配置文件,在该文件中可以配置如下内容:
server.port=8082
2.2.11 启动测试
2.2.12 优化
我们在使用RestTemplate发送请求的时候,底层其实使用的JDK中的HttpURLConnection来进行请求的发送,其实RestTemplate底层的实现也可以使用一些第三方的工具类比如: HttpClient , OkHttp
使用HttpClient
<!-- 添加HttpClient工具 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency>
@Bean publicRestTemplate restTemplate() { returnnew RestTemplate(new HttpComponentsClientHttpRequestFactory()); }
怎么证明底层使用的就是HttpClient呢? 我们可以将HttpClient的依赖包删除掉,项目在启动的时候就报错,那么就说明底层使用的就是HttpClient
使用OkHttp
okhttp是一个封装URL,比HttpClient更友好易用的工具。目前似乎okhttp更流行一些。
<!-- 添加OkHttp依赖 --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.9.0</version> </dependency>
@Bean publicRestTemplate restTemplate() { returnnew RestTemplate(new OkHttp3ClientHttpRequestFactory()); }
2.3 发现问题与解决问题
2.3.1 问题描述
在刚才的服务调用过程中我们的商品服务地址是直接写死在程序中,存在硬编码问题
如果商品微服务部署了多个,那么我们订单微服务如何去调用呢?
2.3.2 问题处理
1. 关于硬编码的问题我们可以使用配置文件处理,我们可以将地址信息编写到配置文件中,然后读取配置文件获取请求地址信息.
在配置文件中加入如下配置:
itcast.item.url=http://127.0.0.1:8081/item/
修改ItemService的实现,通过@Value注解获取该值
package cn.itcast.microservice.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import cn.itcast.microservice.pojo.Item; @Service public class ItemService { @Autowired private RestTemplate restTemplate ; @Value("${itcast.item.url}") private String itemUrl ; /** * 根据商品的id进行查询 * @param id * @return */ public Item queryById(Long id) { // 我们也可以使用spring boot给我们提供的另个一个类RestTemplate,来发送Http请求 Item item = restTemplate.getForObject(itemUrl + id, Item.class) ; // 返回 return item ; } }
注: 我们本次的解决方案只是一种临时的处理方案,如果我们商品微服务的ip地址发送了改变,那么我们对应的订单微服务的配置文件也需要做响应的改变.因此这种处理方案并没有本质的解决硬编码的问题.
2. 如果商品微服务部署了多个,那么我们订单微服务如何去调用呢?
关于这个问题,有的开发人员可能会想. 我们可以将多个商品微服务的地址配置到配置文件中,然后在进行读取配置文件的地址,进行调用.听起来好像可以,但是我们需要考虑以后问题就是后期维护的问题.
如果商品微服务的我们又添加或者减少了一个部署,相应的我们需要去更改配置文件的内容
如果商品微服务的ip地址发送了改变,那么我们也需要相应的修改配置文件的地址
所以我们自己这样实现比较麻烦,我们可以使用服务注册于发现机制来完成。
3 Spring Cloud快速入门
服务注册于发现机制架构图如下:
由上图可以看出:
1、 服务提供者将服务注册到注册中心
2、 服务消费者通过注册中心查找服务
3、 查找到服务后进行调用(这里就是无需硬编码url的解决方案)
3.1 注册中心Eureka
Spring Cloud提供了多种注册中心的支持,如:Eureka、ZooKeeper等。推荐使用Eureka。
Spring Cloud Eureka是Spring Cloud Netflix微服务套件中的一部分,它基于Netflix Eureka做了二次封装。主要负责完成微服务架构中的服务治理功能。
原理如下图所示:
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互
在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
3.2 编写Eureka Server
3.2.1 pom.xml
<projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.microservice</groupId> <artifactId>itcast-microservice-eureka</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 定义变量 --> <properties> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <!-- 导入Spring Cloud的依赖管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <!-- 导入Eureka服务的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> </project>
3.2.2 启动类
package cn.itcat.microservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer //申明这是一个Eureka服务端 @SpringBootApplication publicclassEurekaServer { publicstaticvoid main(String[] args) { SpringApplication.run(EurekaServer.class, args) ; } }
3.2.3 配置文件
#服务端口号 server.port=6868 # 是否需要将自己注册到注册中心中,因为本身就是一个注册中心,所以不需要将自己注册到注册中心中 eureka.client.registerWithEureka=false # 是否从注册中心中获取注册信息 eureka.client.fetchRegistry=false # 客户端和服务端进行交互的地址 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:${server.port}/eureka/
3.2.4 启动程序访问服务端
访问地址: http://localhost:6868/
3.3 商品微服务注册到注册中心
接下来,我们需要将商品的微服务注册到Eureka服务中。
3.3.1 修改pom文件
引入Spring Cloud的管理依赖以及Eureka服务依赖。
<projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.microservice</groupId> <artifactId>itcast-micorservice-item</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 定义变量 --> <properties> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <!-- 导入Spring Cloud的依赖管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- 加入web的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<!-- 导入Eureka服务的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> </project>
3.3.2 修改配置文件
#应用端口号 server.port=8081 #应用名称 spring.application.name=itcast-microservice-item # 是否需要将自己注册到注册中心中,默认值true eureka.client.registerWithEureka=true # 是否从注册中心中获取注册信息,默认值true eureka.client.fetchRegistry=false # 客户端和服务端进行交互的地址 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:6868/eureka/ #将自己的ip地址注册到Eureka服务中 eureka.instance.prefer-ip-address=true
3.3.3 修改启动类
package cn.itcast.microservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient// 声明这是Eureka的客户端 @SpringBootApplication// 声明这是一个Spring Boot项目 public class ItemApplication { public static void main(String[] args) { SpringApplication.run(ItemApplication.class, args); } }
3.3.4 启动商品微服务
至此我们就已经将商品微服务注册到Eureka注册中心了.
3.4 订单系统从Eureka中发现服务
3.4.1 修改pom.xml
之前我们在订单系统中是将商品微服务的地址进行了硬编码,现在,由于已经将商品服务注册到Eureka中,所以,只需要从Eureka中发现服务即可。
引入Spring Cloud的管理依赖以及Eureka服务依赖。
<projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.microservice</groupId> <artifactId>itcast-microservice-order</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 定义变量 --> <properties> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <!-- 导入Spring Cloud的依赖管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- 加入web的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 添加OkHttp依赖 --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> </dependency> <!-- 导入Eureka服务的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> </project>
3.4.2 修改配置文件
#应用端口号 server.port=8082 itcast.item.url=http://127.0.0.1:8081/item/ #应用名称 spring.application.name=itcast-microservice-order # 是否需要将自己注册到注册中心中,默认值true eureka.client.registerWithEureka=false # 是否从注册中心中获取注册信息, 默认值true eureka.client.fetchRegistry=true # 客户端和服务端进行交互的地址 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:6868/eureka/
3.4.3 修改ItemService
package cn.itcast.microservice.service;
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import cn.itcast.microservice.pojo.Item; @Service public class ItemService { @Autowired private RestTemplate restTemplate ; @Autowired private DiscoveryClient discoveryClient ; /** * 根据商品的id进行查询 * @param id * @return */ public Item queryById(Long id) { // 获取商品微服务服务列表 String itemServiceId = "itcast-microservice-item" ; List<ServiceInstance> instances = discoveryClient.getInstances(itemServiceId) ; if(instances.isEmpty()) { return null ; } // 获取实例对象 ServiceInstance instance = instances.get(0) ; String url = "http://" + instance.getHost() + ":" + instance.getPort() ; // 发送请求 Item item = restTemplate.getForObject(url + "/item/" + id, Item.class) ; // 返回 return item ; } }
3.4.4 修改启动
package cn.itcast.microservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Bean; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @EnableDiscoveryClient// 声明这是一个Eureka的客户端 @SpringBootApplication public class OrderApplication { // 程序入口 public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args) ; } }
3.4.5 启动测试
响应的数据如下:
可以看到以及获取到数据,但是,我们发现响应的数据变成了xml结构。
3.4.6 解决响应变成xml的问题
由于我们引入了eureka server的依赖,导致破坏了之前SpringMVC默认的配置,从而导致了响应成了xml。
解决方法:排除eureka server中的xml依赖,如下:
<!-- 导入Eureka服务的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> <exclusions> <exclusion> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </exclusion> </exclusions> </dependency>
测试
注意:在Eureka的服务端不能排除XML依赖,否则启动不了Eureka Server