『Java微服务实践』201. 使用Spring Boot构建第一个API

原文首发于『程序员精进』博客,原文链接:『Java微服务实践』201. 使用Spring Boot构建第一个API

得力于强力的Spring Boot框架,使得在Java领域开发微服务变得简单轻松。Spring Boot是个基于Spring依赖注入框架之上的快速开发及发布就绪(production-ready)框架,是在Java领域可以用来构建微服务的框架之一。在本文中将以实践的方式来介绍Spring Boot框架,以及使用Spring Boot来构建RESTful风格的微服务。在最后我们再来看看Spring Boot框架里面哪些特性可以帮助我们构建发布就绪(production-ready)的微服务。以下是你在本文中将学到的内容:

  • 安装最新Spring Boot开发环境
  • 使用Spring Boot开发RESTful风格的微服务
  • 使用Spring Boot特性来构建发布就绪(production-ready)的微服务

开发环境准备

在使用Spring Boot开发微服务之前需要安装以下环境:

其它可选的IDE有IntelliJ IDEA, NetBeans和Eclipse,为了Spring Boot相关组件的引入,所以本文就用STS来做演示了,同样,依赖管理工具Maven也可以换成Gradle,根据你自己的熟悉程度来选了。在本文中的Spring相关框架版本为:

  • Spring Boot 2.0.3.RELEASE
  • Spring Framework 5.0.7.RELEASE

使用Spring Boot作为微服务框架进行微服务开发,为了方便使用Spring生态的各类框架和工具,因此我们还需要准备相应的Spring Boot工具环境。

Spring Boot CLI快速开始

我们将使用Spring Boot CLI进行我们第一个Spring Boot应用的初始化,当然你可以使用STS或Spring Initializr来进行创建,这两种方法我们将在后面介绍,你日后可以根据自己的使用习惯来选择。如果你使用STS作为IDE开发的话,使用STS构建Spring Boot应用很简单,如果你习惯命令行操作的话,Spring Boot CLI是个不错的选择,如果你不想安装STS或Spring Boot CLI的话,直接使用Spring Initializr这是可以的。实际上Spring Boot CLI就是Spring Initializr的命令行版本。

当你安装完毕Spring Boot CLI后,你可以通过命令行查看下安装的版本情况。

$ spring --version
Spring CLI v1.4.0.RELEASE

如果你能够看到Spring CLI的版本信息,表明你的Spring Boot CLI已经安装完成,接下来,我们使用Spring Boot CLI来创建个示例项目:

spring init --build maven --groupId io.junq.examples  --version 1.0.0 --java-version 1.8 --dependencies web  --name hello-springboot --package-name io.junq.examples.boot hello-springboot

在执行完上面的命令后,会生成一个名为hello-springboot的目录,该目录里面就是hello-springboot项目的完整文件了。spring init命令还有一些可选参数,我们列一些常用的出来简单讲述下:

--build
  指定所使用的构建管理(依赖关系管理)工具。可选项为maven或gradle。

--groupId
  maven项目的groupId,会反映在pom.xml中,需要注意的是,设置了这个参数并不会指定包名,包名需要用 package-name参数来进行指定。

--package-name
  应用的包名。

--version
  应用的版本号,如 1.0.0

--java-version
  JDK版本

--dependencies
  该应用依赖的Spring组件列表,可以选择多个,以逗号分隔。

现在你可以进入hello-springboot目录,执行以下命令:

$ mvn spring-boot:run

如果不报错的话,你的终端或命令行应该输出类似以下日志:


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.3.RELEASE)

2017-02-10 15:39:43.321  INFO 64362 --- [           main] i.j.e.boot.HelloSpringbootApplication    : Starting HelloSpringbootApplication on junqiangs-MacBook-Pro.local with PID 64362 (started by junqiangliu in /Users/junqiangliu/Documents/james/courses/StuQ-1160 Java微服务/examples/hello-springboot)
2017-02-10 15:39:43.324  INFO 64362 --- [           main] i.j.e.boot.HelloSpringbootApplication    : No active profile set, falling back to default profiles: default
2017-02-10 15:39:43.406  INFO 64362 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2e6aff98: startup date [Fri Feb 10 15:39:43 CST 2017]; root of context hierarchy
2017-02-10 15:39:44.538  INFO 64362 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration' of type [class org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-02-10 15:39:44.651  INFO 64362 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'validator' of type [class org.springframework.validation.beanvalidation.LocalValidatorFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-02-10 15:39:44.966  INFO 64362 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-02-10 15:39:44.981  INFO 64362 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-02-10 15:39:44.983  INFO 64362 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.11
2017-02-10 15:39:45.150  INFO 64362 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-02-10 15:39:45.151  INFO 64362 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1745 ms
2017-02-10 15:39:45.323  INFO 64362 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-02-10 15:39:45.329  INFO 64362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-02-10 15:39:45.329  INFO 64362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-02-10 15:39:45.329  INFO 64362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-02-10 15:39:45.330  INFO 64362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-02-10 15:39:45.627  INFO 64362 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2e6aff98: startup date [Fri Feb 10 15:39:43 CST 2017]; root of context hierarchy
2017-02-10 15:39:45.720  INFO 64362 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-02-10 15:39:45.722  INFO 64362 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-02-10 15:39:45.759  INFO 64362 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-02-10 15:39:45.759  INFO 64362 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-02-10 15:39:45.810  INFO 64362 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-02-10 15:39:46.001  INFO 64362 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-02-10 15:39:46.080  INFO 64362 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-02-10 15:39:46.085  INFO 64362 --- [           main] i.j.e.boot.HelloSpringbootApplication    : Started HelloSpringbootApplication in 3.35 seconds (JVM running for 224.399)

现在你的第一个Spring Boot应用已经成功运行,打开浏览器访问 http://localhost:8080 ,你会看到如下内容:

Whitelabel error page

这个是一个默认的错误页面,因为现在什么REST API代码都还没有编写,所以正常咯。

STS快速开始

如果你不太习惯用命令行进行操作,接下来会告诉你如何使用STS进行Spring Boot应用的创建。

  1. 首先我们打开STS程序,在菜单栏依次选择 “文件(File) -> 新建(New)-> Spring Starter Project”,如下图:
创建新项目
  1. 接下来在创建项目窗口来设置项目信息,项目名称为“hello-springboot”、类型选“Maven”、Java版本为“1.8”、Group Id为io.junq.examples、Artifact为“hello-springboot”、包名为“io.junq.examples.boot”,注意此处的打包方式(Packaging)我们选择了“jar”,与传统Web应用不同,微服务应用所运行的Java容器环境(指Tomcat、Jetty等)一般为自己内嵌,具体项目配置如下图所示:
示例Spring Boot项目创建详情
  1. 现在你会看到关于Spring组件的选择,此处效果和Spring Boot CLI命令参数的--dependencies一样的作用,在此选择Web,然后点击完成,如下图所示:
Spring组件选择
  1. 此时你的项目列表窗口应该能够看到你刚才创建的项目了,如下图所示:
项目浏览窗口

\

  1. 在“hello-springboot”项目上点击右键,依次选择“运行(Run As) -> Spring Boot App”,如下图所示:
运行项目
  1. 在不报错的情况下,你这时应该在控制台窗口看到如下画面:
项目启动时控制台
  1. 现在你的第一个Spring Boot应用已经成功运行,打开浏览器访问 http://localhost:8080 ,你会看到如下内容:
Whitelabel error page

这个是一个默认的错误页面,因为现在什么REST API代码都还没有编写,所以正常咯。

Hello World

我们现在已经有了一个可以运行的Spring Boot应用,接下来我们添加一些简单的方法来实现功能。现在我们来添加一个REST API,路径为 /api/hello,访问此API时,会返回“Hello world,Spring Boot rocks。”的消息。首先定位到“src/main/java/io/junq/examples/boot”在该目录下创建HelloRestController.java,该类负责 /api 这个API路径的所有业务逻辑,如下所示:

public class HelloRestController {

    public String hello() {
        return "Hello world, Spring Boot rocks.";
    }

}

添加 HTTP 请求入口

在上面我们创建了“HelloRestController”类想来它负责 /api 这个路径下的业务请求,所以我们要给其添加 HTTP Endpoints 才能够被Spring Boot框架正式处理,调用它来处理对应API路径下的业务逻辑,以下先介绍两个关键的注解:

@RestController

  告诉 Spring 这个控制器类可以用来作为HTTP请求入口,如GET、POST、PUT、DELETE等。

@RequestMapping

  表示将映射HTTP地址的哪个部分到Java代码上,这里的Java代码可以是类、方法等。

我们将 “/api” 的HTTP请求入口绑定至 HelloRestController 这个控制器类上,将 “/api/hello” 映射到 “hello” 方法上,如下所示:

@RestController
@RequestMapping("/api")
public class HelloRestController {

    @RequestMapping(method = RequestMethod.GET, value = "/hello",
            produces = "text/plain")
    public String hello() {
        return "Hello world, Spring Boot rocks.";
    }

}

这是再运行项目,使用浏览器访问 http://localhost:8080/api/hello ,你会看到如下内容:

Hello World, Spring Boot

附录:环境安装

以下的安装教程以MacOS作为示例环境,对于Linux用户来说应该差不多,对于Windows来说就不太一样了。

Spring Boot CLI 安装

Spring Boot CLI 2.0.3的安装教程如下,安装过程来源于官方网站,大家想了解详情,可以访问。https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started-installing-spring-boot.html#getting-started-installing-the-cli

建议使用SDKMAN!进行安装。

手动安装

从Spring仓库下载Spring CLI二进制文件,以下两个压缩包选择一个即可:

下载完压缩包解压后,文件夹里面会有INSTALL.txt文件,根据安装指引文件进行安装即可。

使用SDKMAN!安装

安装SDKMAN!

安装SDKMAN!在Unix-Like的系统上十分简单,在Mac OSX, Linux, Cygwin, Solaris和FreeBSD系统上可以使用终端进行安装,现在SDKMAN!安装脚本现在支持Bash和ZSH。

$ curl -s "https://get.sdkman.io" | bash

当提示安全完成后,在终端中输入以下命令,将SDKMAN!添加到环境变量中。

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

然后便可以执行sdk命令,进行版本查看,版本查看返回版本号成功就代表SDKMAN!安装成功了。

$ sdk version
SDKMAN 5.6.4+305

安装Spring Boot CLI

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

推荐阅读更多精彩内容