微服务分布式架构基础与实战:基于Spring Boot + Spring Cloud
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 【实例】微服务工程Hello World

1.3.1 实例背景

本书采用Eclipse配合Maven进行编程,JDK采用1.8版本,如果使用Idea、STS等相应开发工具,并无任何区别。STS是专门为Spring Boot制作的开发工具,全称为Spring Tool Suite,其中含有各种Spring Boot模板,在引入模板时,会自动生成pom.xml中所需要依赖的文件,但是本书使用Eclipse进行开发。STS基于Eclipse并进行了一定程度的封装,因此其快捷键、代码提示等功能和Eclipse无任何区别。

建议Spring Boot的版本在2.0.0上,因为有一些新特性可以使用。

本实例将创建boot_01工程,首先使用Maven插件集成Spring Boot微服务依赖,再通过@RestController注解编写REST风格的HTTP接口输出Hello World字符串。

1.3.2 创建Maven Project

在Eclipse工具下进行编程,Spring Boot通常在Maven工具的辅助下创建,因为Spring Boot内部所继承的依赖Jar包太多,Maven能够一次性将Spring Boot所有需要的依赖Jar包下载完成。

因为微服务工程只使用Spring Boot而并非Spring Boot下的一个模块,所以创建的是Maven Project,而不是Maven Module。表1-2所示为Maven工程类型及其含义。

表1-2 Maven工程类型及其含义

1.3.3 使用空Maven Project模板

模板的最大优点是能自动生成pom.xml文件。例如,当需要引入MySQL的驱动包对数据库增删改查时,STS创建工程可进行选择和引入。

如图1-1所示,创建Maven Project工程后选中Create a simple project(skip archetype selection)复选框,即不使用Maven模板。

图1-1

1.3.4 编辑Maven坐标定位及工程名

Maven的一个核心作用是对管理工程的依赖,同时引入所需要的各种Jar包等。为了能自动化地解析任何一个Java构件,Maven必须将依赖Jar包或其他资源进行唯一标识,标识即Maven坐标。Maven坐标是对工程依赖的基础。拥有其他工程的Maven坐标才能引用其他工程,或被其他工程所引用。Maven坐标的作用好像Maven世界中的身份证一样。

Maven坐标通过Group Id、Artifact Id、Version、Packaging、Name、Decription等元素来定义,如同坐标轴中的X轴、Y轴一样。

Group Id:定义当前Maven工程隶属的实际项目。图1-2中建立的Jar文件默认将处于C:\Users\Administrator\.m2\repository\org\zfx\boot文件夹中,在Maven世界里别人依赖此工程,也会处于$Maven_Home\.m2\repository\org\zfx\boot文件夹中。通常命名会表明该工程处于各项目中的哪个位置,以方便理解。

图1-2

Artifact Id:定义Group Id位置下实际工程的名字,推荐与工程名保持一致,Maven生成的构件其文件名都会以Artifact Id作为开头。

Version:定义当前Maven工程所在的版本,因为作为名字后缀存储,所以建议尽量简短,方便后续对其进行维护。

Packaging:定义Maven的打包方式,通常为Jar文件或War文件。若不对其进行定义,则默认为Jar文件。

Decription:对Maven工程进行描述的内容,通常不会使用。

图1-2所示为输入该工程的Maven坐标等基本信息。

1.3.5 检查Maven目录结构

好的目录结构方便开发人员编写程序,也将为程序在未来使用过程中的维护工作打下良好的基础。

Maven目录结构是业界公认的最佳目录结构,为开发者提供了缺省的标准目录模板,Eclipse中Maven目录结构如图1-3所示。Idea的Maven目录结构与Eclipse的Maven目录结构略有不同。

图1-3

Maven目录结构释义如表1-3所示。

表1-3 Maven目录结构释义

1.3.6 编写Pom文件

pom.xml文件是Maven插件用来引入相关依赖Jar包的管理文件。其中,pom.xml内的<parent>标签代表该工程继承父类Maven工程的坐标,并且将会集成父类Maven下所有相关依赖,类似于Java的extend。<dependencies>标签下引入其他相关Maven工程坐标。

pom.xml文件代码如下。

更新Pom文件前要了解当前计算机上是否含有JDK1.8版本,JDK1.7或以下版本需尝试使用spring-boot-starter-parent,版本为1.5.3.RELEASE。而JDK1.7使用Spring Boot 2.0以上版本会报Pom文件相关编译错误。具体可查询Spring.io网站信息。

编写本书时Spring Boot最高版本为2.0.x。

1.若无法从parent里进行继承

若工程有其他的包需要继承,则直接在pom.xml文件中对Spring Boot进行引入,即不使用<parent></parent>标签,pom.xml文件部分代码如下。

注意,如果没有编写<dependencyManagement></dependencyManagement>标签进行定义,经常会报错。Spring Boot官方文档同样编写了该标签。

2.保存pom.xml文件会报错误

在Maven工程的pom.xml文件被更改并保存的情况下,工程会报如下错误:

工程报错效果如图1-4所示。该错误是未更新Maven工程依赖的报错,原因是虽然进行了依赖但并未导入Maven相关依赖包。此时需要对Maven工程进行Update操作。

1.3.7 Spring Boot依赖包的导入

Maven Update Project是指Maven进行了一系列跟自身配置有关的操作,如更新SVN、更新工程关联、编译工程、构建发布、下载Jar包、下载Jar doc文件等。

图1-4

如图1-5所示,选择Update Project更新Maven工程依赖,可解决图1.4中在编写完pom.xml相关依赖并保存时未更新Maven工程的错误。

图1-5

图1-6中Maven Update导入文件依赖包的选项释义如下。

图1-6

Offline:启动离线模式,即不会通过Maven镜像地址下载资源,而重新检查自身仓库内的资源,内网开发的公司若没有自身的Maven镜像,则经常会使用离线模式。

Force Update of Snapshots/Releases:强制更新模式,在Update dependencies更新依赖下,强制更新模式代表无论此时所有依赖包是否处于正常依赖状态,都会重新到Maven仓库中进行检查,并重新把该包导入工程中。若工程在导入包后仍然发生错误,有些包没有被正常导入,则需要启动强制更新模式进行强制重新导入。

如果编写了一个zfx_common-1.0.jar包,已经导入工程中,但是编程人员手动在本地仓库中删除了该依赖包,并置入一个更新后的zfx_common-1.0.jar依赖包(但两个版本拥有相同的名称和版本号),就需要启动离线模式加强制更新模式,离线模式加强制更新模式会在自身的工程中删除原有zfx_common-1.0.jar包,并依赖更新后的同版本号的zfx_common-1.0.jar依赖包。

Update project configuration from pom.xml:根据pom.xml的配置文件更新工程。

Refresh workspace resources from local filesystem:从本地仓库系统刷新工作区资源。若仓库中含有该依赖包,则从仓库中进行获取;若仓库中没有该依赖包,则会通过Maven镜像地址进行下载。镜像地址在$Maven_HOME/config/setting.xml文件中配置。

Clean projects:重新编译工程。

1.3.8 编写Spring Boot启动类

Spring Boot微服务工程都是JavaSE工程,因此需要main方法来启动并加载Spring容器等相关操作。启动核心代码如下。

上述两种都是Spring Boot微服务的启动核心代码。启动类Application-Main.java代码如下(启动类名称可自行定义)。

1.3.9 编写Spring Boot接口

在boot_01工程中创建HelloWorld.java类,在HelloWorld.java类中编写REST风格的HTTP接口代码如下。

@RestController注解相当于@Controller注解和@ResponseBody注解的集成注解,@RestController注解可直接返回json格式字符串,不需要新增其他代码。

@RequestMapping("/")是springMVC的注解,映射路径给外部进行访问。若该工程中含有相同的@RequestMapping路径,则会发生启动报错异常。

1.3.10 当前项目结构

ApplicationMain放置在com.zfx文件夹中,而其他文件则放置在com.zfx.xxx中,原因是Spring Boot的@SpringBootApplication只能扫描com.zfx的下级文件夹。

若某个@Component组件类注解放置在com.zfx同级文件夹下,则无法被@SpringBoot-Application注解扫描到,也无法被注册到Spring的Application容器内。当前项目结构如图1-7所示。

图1-7

1.3.11 启动工程

因为Spring Boot将Tomcat集成到自身上的框架,所以通过main命令可启动。

启动项目时直接在ApplicationMain.java类中运行Run As→Java Application命令即可,如图1-8所示。

图1-8

1.3.12 Spring Boot初始化启动后

根据日志最后看到部分启动信息如下。

Spring Boot内嵌Tomcat默认加载端口号为8080。

Spring Boot默认不需要输入工程名。如果有特殊需要,可在配置文件中增加自定义工程名配置。如果@RequestMapping写成@RequestMapping("HelloWorld"),访问的路径为localhost:8080/HelloWorld,后续对工程使用Spring Cloud进行控制时可以用增加工程名的方式来区分不同的微服务。

启动工程后,输入localhost:8080调用工程中的相关接口,执行结果如图1-9所示。

图1-9

如果访问localhost:8080/XXX,会报找不到接口的错误。这是因为Spring Boot不像Tomcat自带了一个欢迎页面。找不到相关接口报错提示如图1-10所示。

图1-10

注意,HTTP-404错误只在前台报错,后台正常打印日志且不输出“错误”信息,错误日志如下。

1.3.13 实例易错点

1.缺少启动注解错误

SpringContext容器没有启动成功的报错信息如下,通常是因为缺少@EnableAuto-Configuration注解所引起的,此时应检查main方法的类是否含有@EnableAutoConfiguration注解或@SpringBootApplication注解修饰。

2.@RequestMapping路径重复错误

@RequestMapping路径重复错误是初学者常见错误之一,错误日志如下。

通常说明@RequestMapping("")在映射路径时,如果某一个路径相同,重复了一次或以上,需要修改成不同的路径名。

注意,下述代码使用@PathVariable注解用来获取URL路径上携带参数的信息,虽然@RequestMapping(/HelloWorld/{id})注解中的花括号内使用了不同的命名方式,但由于URL路径重复,所以@RequestMapping注解无法正常识别并获取URL路径与其携带的参数,无法正确将URL映射到Java接口中去,因此会引发多个相同路径的错误异常。

以上方法并不会报启动错误。部分启动日志如下。

多个相同路径的错误在运行后调用会报以下错误,找不到相对应的接口函数如图1-11所示。因此应当避免出现多个相同位置的@PathVariable,让维护人员混淆或模糊的写法。

图1-11