利用Spring Cloud实现微服务(四)- 微服务实现与注册

Code Is Only Differentiator

源码:https://github.com/shuxingliu/microservices


一、生成项目文件(设置开发环境)

SpringCloud是Spring Boot的子集,我们可以使用Spring Boot预先配置网页(http://start.spring.io)来选择构建工具(Maven、Gradle)、项目元元数据(组名称、工件名称)。如果我们需要更多选择,我们需要点击"Switch to Full Version",在全部版本里,我们可以编辑更多的项目元数据信息(依赖项、打包格式、Java版本等),并选择安全、Web服务器、关系型/非关系型数据库、云服务的注册/配置/路由/发现、微服务的熔断等依赖项。我们要感谢Pivotol为我们提供了Spring Boot这么好的起点,大大简化了JavaWeb应用的开发。

本节示例中,我们使用Maven来作为构建工具,工件命名为booking car,是一个开发打车微服务的演示项目,打包格式为jar,使用Java最新版本Java1.8,包的名称设为:com.accenture.j2c.bookingcar,如下图所示。

在页面下面的依赖项,我们选择了Web、Eureka Server等依赖项。

选择依赖项后,界面显示如下:

点击Generate Project后,项目文件会打包成“项目名+zip”格式并自动下载到本地

我们使用NetBeans作为IDE,从项目zip文件导入刚才的项目

在导入项目的过程中,如果本地Maven库里没有声明的依赖项,NetBeans会给我们提示,我们点击“Resolve”即可,NetBeans会自动下载缺失的依赖项到本地Maven库里。

项目文件导入后,我们发现项目中已经有下列文件:

我们可以看到项目的包名为com.accenture.j2c.bookingcar

其中,main程序位于BookingcarApplication.java内,main调用了Spring Boot的SpringApplication.run()方法来启动应用程序。

二、EurekaClient的实现

为了能使微服务自动在Eureka服务器上注册,bookingcar应用要声明为Eureka Client。通过以下的两个步骤声明即可。

1. 导入包:org.springframework.cloud.netflix.eureka.EnableEurekaClient;

2. 添加注解:@EnableEurekaClient

三、实体、值对象的实现

在上一节的分析中,我们也可以发现,聚合中的实体、值对象位于战术建模的最底层,聚合、服务、存储库都依赖于实体、值对象。领域事务的实现过于复杂,我们在本次演示里暂不涉及,以后可以单独开辟一个单独的章节将领域事件的实现。

我们把实体放到包com.accenture.j2c.bookingcar.domain.entity里,把值对象放到包:com.accenture.j2c.bookingcar.domain.vo里

各个实体类的实现:

1. 抽象类Entity的实现

对于所有实体,ID和name都是常见的,因此,我们可以如下定义抽象类Entity作为实体的抽象。

Entity实现代码如下所示:

2. Order聚合的实现

Order是打车管理系统中的核心聚合,Order实体会作为Order聚合的聚合根。对Order的描述放到OrderVO里。User及Driver的实现同Order类似,不再累述。

OrderVO的实现:

Order实体的实现:

四、存储库类的实现

在本示例中,对于每一类实体,包括用户、司机、订单等,在某个时段里都会存在多个实例。比如,我们会有很多的用户,张三、李四、王二麻子,有很多的司机,有很多的订单。对于每一类实体,我们需要有个统一的接口来保存并引用这些实体。比如,对于用户实体,我们应该有一个用户存储库,用来存储所有的用户,管理用户的增、删、改、查。对于司机、订单也是类似,也需要分别有一个存储库来对应。

我们需要三个存储库:UserRepository,DriverRepository, OrderRepository。

开始时,我们首先创建两个抽象:ReadOnlyRepository和Repository。ReadOnlyRepository用于提供只读操作的抽象,例如get,getall等。而Repository用于执行所有类型的操作,包括增、删、改、查。

1. ReadOnlyRepository的实现如下:

2. Repository在ReadOnlyRepository基础上进行扩展,提供增加、删除、更新等操作接口,实现如下:

3. UserRepository、DriverRepository、OrderRepository接口在Repository接口上扩展,UserRepository、DriverRepository增加了containsName以及findByName两个操作,OrderRepository还添加了findByUserId接口,通过用户Id找到对应订单。

仅以OrderRepository为例展示实现代码:

4. 仓储库的实现

在Spring框架中,使用@Repository注解来定义实现存储库的bean。另外,我们把演示数据直接放到内存中,代替实际的数据库操作。

本次例程里,实现了用户和订单的仓储库。仅以订单的仓储库实现为例:

五、领域服务类的实现

领域服务定义了CRUD和一些界面操作。

我们抽象出ReadOnlyBaseService基类和BaseService基类,以及DomainService接口

1. ReadOnlyBaseService的实现如下:

2. BaseService继承于ReadOnlyBaseService,实现如下:

3. 在Spring框架中,使用@Repository注解来定义实现领域服务的bean。对订单操作的领域服务实现如下:

六、REST控制器类的实现

微服务最终会提供Restful接口给外面的程序调用。在微服务实现中,REST控制器是必不可少的。REST控制器用来处理HTTP请求,有四个常用的注解。

@RestController:类级注解,表明该类是REST控制器,用来处理HTTP请求,即表明该类可以提供Restful接口。

@RequestMapping:1)类级别,将URI映射到类上;2)方法级别:将路径映射到不同的方法。从这儿可以看出,一个微服务可以通过@RequestMapping注解映射不同的接口。

@RequestParam和PathVariable用来传递HTTP请求的参数。在someUrl/{param=value}中的param可以通过@RequestParam将HTTP请求的参数和方法的参数绑定,而someUrl/{paramId}的paramId可通过@Pathvariable注解绑定它传过来的值到方法的参数上。

本例程中,为了更好地演示,除了实现了上节里设计的使用用户Id查找订单的微服务接口外,还实现了使用订单Id查询订单、使用用户id查找用户,使用用户名字查找用户等接口。这四个接口的端点如下:

使用用户Id查找订单:http://.../v1/order?userid={userid}

使用订单id查询订单:http://.../v1/order/{id}

使用用户id查找用户:http://.../v1/user/{id}

使用用户名称查找用户:http://.../v1/user?name={name}

我们使用了两个控制器类UserController和OrderController来实现上面的四个接口端点

1. UserController的实现如下:

2. OrderController的实现如下:

七. 应用属性的配置

要使微服务自动注册到Eureka

Server里,我们要配置应用的属性。

应用属性的文件名称为application.properties,在项目中的路径如下:

本实现中,配置如下:

spring.application.name=bookingcar-lsx

spring.freemarker.enabled=false

spring.thymeleaf.cache=false

eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

server.port=2227

八、测试REST API

1. 按照系列文章中第一部分的描述,启动Eureka Server



2. 选择bookingcar项目,右键弹出快捷菜单

3. 在Run Maven的窗口里,Goals输入"spring-boot:run"

4. Bookingcar应用启动后,刷新Eureka Server的界面,我们会发现bookingcar的微服务已经在“Instances currently registered with Eureka"下

5. 点击微服务后面的链接,我们会进入微服务的入口,输入不同的请求参数,我们可以观察到不同的反馈。

1) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/user/1

查找id为1的用户,结果如下:


2) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/user?name=2

查找用户名为2的用户,结果如下:


3)http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/order/2

查找id为2的订单,结果如下:



4) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/order?userid=1

查找用户id为1的订单集合,结果如下:

利用Spring Cloud实现微服务(七)- 内部调用

利用Spring Cloud实现微服务(六)- 服务网关

利用Spring Cloud实现微服务(五)- 负载均衡

利用Spring Cloud实现微服务(三)- 业务领域驱动微服务设计

利用Spring Cloud实现微服务(二)--领域驱动设计

利用Spring Cloud实现微服务(一):Eureka服务器

推荐阅读更多精彩内容