得力于强力的Spring Boot框架,使得在Java领域开发微服务变得简单轻松。Spring Boot是个基于Spring依赖注入框架之上的快速开发及发布就绪(production-ready)框架,是在Java领域可以用来构建微服务的框架之一。在本文中将以实践的方式来介绍Spring Boot框架,以及使用Spring Boot来构建RESTful风格的微服务。在最后我们再来看看Spring Boot框架里面哪些特性可以帮助我们构建发布就绪(production-ready)的微服务。以下是你在本文中将学到的内容:
在使用Spring Boot开发微服务之前需要安装以下环境:
Oracle JDK8
Apache Maven 3.3+
Spring Tool Suite
其它可选的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 2.0.3
我们将使用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 ,你会看到如下内容:
这个是一个默认的错误页面,因为现在什么REST API代码都还没有编写,所以正常咯。
我们现在已经有了一个可以运行的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."; } }
在上面我们创建了“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 ,你会看到如下内容: