利用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服务器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容