首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第3章 Spring Boot快速开始Hello World本章源代码

第3章 Spring Boot快速开始Hello World本章源代码

作者头像
一个会写诗的程序员
发布2018-08-20 09:59:29
3870
发布2018-08-20 09:59:29
举报

第3章 Spring Boot快速开始Hello World

3.1 SpringBoot版的Restful Hello,World

3.1.1 Spring Boot CLI groovy版Hello World

首先安装Spring Boot CLI,参考文档:http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-installing-the-cli

在命令行验证spring环境安装成功:

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

随便打开编辑器,敲入如下代码:

 @Controller
 class HelloController{
      @RequestMapping("/hello")
      @ResponseBody
      String hello(){
          return "Hello World!"
      }
 }

然后在命令行执行:

$ spring run HelloController.groovy

你将看到如下输出日志:

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

2017-04-04 21:37:29.685  INFO 87317 --- [       runner-0] o.s.boot.SpringApplication               : Starting application on jacks-MacBook-Air.local with PID 87317 (/Users/jack/.m2/repository/org/springframework/boot/spring-boot/1.3.6.RELEASE/spring-boot-1.3.6.RELEASE.jar started by jack in /Users/jack/book)
2017-04-04 21:37:29.699  INFO 87317 --- [       runner-0] o.s.boot.SpringApplication               : No active profile set, falling back to default profiles: default
2017-04-04 21:37:30.367  INFO 87317 --- [       runner-0] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@30cc0018: startup date [Tue Apr 04 21:37:30 CST 2017]; root of context hierarchy
2017-04-04 21:37:33.757  INFO 87317 --- [       runner-0] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-04-04 21:37:33.790  INFO 87317 --- [       runner-0] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-04-04 21:37:33.793  INFO 87317 --- [       runner-0] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.36
2017-04-04 21:37:33.986  INFO 87317 --- [ost-startStop-1] org.apache.catalina.loader.WebappLoader  : Unknown loader org.springframework.boot.cli.compiler.ExtendedGroovyClassLoader$DefaultScopeParentClassLoader@67cc18dd class org.springframework.boot.cli.compiler.ExtendedGroovyClassLoader$DefaultScopeParentClassLoader
2017-04-04 21:37:34.037  INFO 87317 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-04-04 21:37:34.038  INFO 87317 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3673 ms
2017-04-04 21:37:34.538  INFO 87317 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2017-04-04 21:37:34.552  INFO 87317 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-04-04 21:37:34.553  INFO 87317 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-04-04 21:37:34.553  INFO 87317 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-04-04 21:37:34.553  INFO 87317 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2017-04-04 21:37:35.309  INFO 87317 --- [       runner-0] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@30cc0018: startup date [Tue Apr 04 21:37:30 CST 2017]; root of context hierarchy
2017-04-04 21:37:35.482  INFO 87317 --- [       runner-0] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello]}" onto public java.lang.String HelloController.hello()
2017-04-04 21:37:35.485  INFO 87317 --- [       runner-0] 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-04-04 21:37:35.486  INFO 87317 --- [       runner-0] 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-04-04 21:37:35.523  INFO 87317 --- [       runner-0] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-04 21:37:35.524  INFO 87317 --- [       runner-0] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-04 21:37:35.606  INFO 87317 --- [       runner-0] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-04 21:37:36.225  INFO 87317 --- [       runner-0] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-04-04 21:37:36.397  INFO 87317 --- [       runner-0] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-04-04 21:37:36.403  INFO 87317 --- [       runner-0] o.s.boot.SpringApplication               : Started application in 8.263 seconds (JVM running for 12.897)

一个极简的Restful Hello World就搞定了。浏览器访问:http://localhost:8080/hello(或者curl http://localhost:8080/hello

你会看到输出:

Hello World!

3.1.2 常规的Java版的Hello World

1.命令行输入:

$ spring init -dweb --build gradle
Using service at https://start.spring.io

Content saved to 'demo.zip'

2.解压zip,导入idea中

你将看到如下一个Demo Application

.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── DemoApplication.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── java
            └── com
                └── example
                    └── DemoApplicationTests.java

14 directories, 8 files

其中DemoApplication.java代码如下:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

build.gradle配置文件如下:

buildscript {
    ext {
        springBootVersion = '1.5.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

OK,我们直接Run

Run

同样的,你讲看到如下日志:

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

2017-04-04 22:51:58.995  INFO 89676 --- [           main] com.example.DemoApplication              : Starting DemoApplication on jacks-MacBook-Air.local with PID 89676 (/Users/jack/book/demo/build/classes/main started by jack in /Users/jack/book/demo)
2017-04-04 22:51:58.998  INFO 89676 --- [           main] com.example.DemoApplication              : No active profile set, falling back to default profiles: default
2017-04-04 22:51:59.191  INFO 89676 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6950e31: startup date [Tue Apr 04 22:51:59 CST 2017]; root of context hierarchy
2017-04-04 22:52:02.718  INFO 89676 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-04-04 22:52:02.750  INFO 89676 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-04-04 22:52:02.754  INFO 89676 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.11
2017-04-04 22:52:02.974  INFO 89676 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-04-04 22:52:02.974  INFO 89676 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3788 ms
2017-04-04 22:52:03.173  INFO 89676 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-04-04 22:52:03.198  INFO 89676 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-04-04 22:52:03.199  INFO 89676 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-04-04 22:52:03.199  INFO 89676 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-04-04 22:52:03.200  INFO 89676 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-04-04 22:52:03.758  INFO 89676 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6950e31: startup date [Tue Apr 04 22:51:59 CST 2017]; root of context hierarchy
2017-04-04 22:52:03.931  INFO 89676 --- [           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-04-04 22:52:03.932  INFO 89676 --- [           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-04-04 22:52:03.986  INFO 89676 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-04 22:52:03.987  INFO 89676 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-04 22:52:04.076  INFO 89676 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-04 22:52:04.334  INFO 89676 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-04-04 22:52:04.447  INFO 89676 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-04-04 22:52:04.455  INFO 89676 --- [           main] com.example.DemoApplication              : Started DemoApplication in 6.41 seconds (JVM running for 7.608)

通过日志,我们可以看到SpringBootApplication大致的启动流程。这个过程中,很大一部分工作是在做Spring应用的初始化。

Initializing Spring embedded WebApplicationContext

同时,嵌入式的servlet容器tomcat的启动,org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext是关键类。对细节感兴趣的可以直接debug一下源码。

上面的代码虽然看不出什么效果。但SpringBootApplication的基本架构流程已经基本在里面了。SpringBoot通过注解@SpringBootApplication,完成了自动配置的工作。(源码参见: org.springframework.boot.autoconfigure.SpringBootApplication)

3.写个HelloWorldController

package com.example.controller;

import java.util.Date;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by jack on 2017/4/4.
 */
@RestController
public class HelloWorldController {
    @RequestMapping("hello")
    String hello() {
        return "Hello World! " + new Date();
    }
}

直接Run DemoApplication,我们可以看到有如下的日志:

...
Mapped "{[/hello]}" onto java.lang.String com.example.controller.HelloWorldController.hello()
...

浏览器访问:http://localhost:8080/hello

我们将看到如下输出:

Hello World! Tue Apr 04 23:08:33 CST 2017

另外,如果是在命令行运行,使用SpringBoot gradle插件的执行:

$gradle bootRun

使用SpringBoot maven插件的执行:

$mvn spring-boot:run

3.2 启动Springboot的自动配置@EnableAutoConfiguration

SpringBoot AutoConfiguration的原理是通过Spring的@Conditional注解实现。@Conditional以编程的方式确定的bean的状态,来决定哪些bean是要初始化到容器中(根据外界条件注册不同Bean)。

@EnableAutoConfiguration的意思是启用Spring应用程序上下文的自动配置,通过扫描CLASSPATH里面所有的组件,然后基于条件来决定是否注册bean来使得Spring的ApplicationContext自动配置。

比如说,Spring检测jdbcTemplate是否在classpath?if true, 看看bean容器里面是否有DataSource ? if true, 配置一个JdbcTemplate的Bean到容器中。

看EnableAutoConfiguration源码:

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

可以发现,这里Import了EnableAutoConfigurationImportSelector。 Import主要是配合Configuration来使用的,用来导出更多的Configuration类,ConfigurationClassPostProcessor会读取Import的内容来实现具体的逻辑。 EnableAutoConfigurationImportSelector实现了DeferredImportSelector接口,并实现了selectImports方法,用来导出Configuration类。

String[] selectImports(AnnotationMetadata importingClassMetadata); 导出的类是通过SpringFactoriesLoader.loadFactoryNames()读取了ClassPath下面的META-INF/spring.factories文件,这个文件内容大致如下:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
......
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

其中EmbeddedServletContainerAutoConfiguration是实现web服务的主要的配置类。这个类会根据当前存在的类的信息注入必要的EmbeddedServletContainerFactory类。 spring-boot-starter-tomcat引入了tomcat的依赖,所以EmbeddedServletContainerAutoConfiguration发现存在Tomcat.class就会注入TomcatEmbeddedServletContainerFactory来内置web容器。

当然,如果你想排除一些bean的自动注入,你可以用Class<?>[] exclude() 或者String[] excludeName()。

SpringBoot在spring-boot-autoconfigure-{版本号}.jar里面提供了很多AutoConfiguration的类来负责注册各种不同的组件。这些组件几乎涵盖了Spring开发中需要的绝大部分的配置。

本章源代码

https://github.com/EasySpringBoot/HelloWorld/tree/hello_world_2017.4.4

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.04.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第3章 Spring Boot快速开始Hello World
    • 3.1 SpringBoot版的Restful Hello,World
      • 3.1.1 Spring Boot CLI groovy版Hello World
      • 3.1.2 常规的Java版的Hello World
    • 3.2 启动Springboot的自动配置@EnableAutoConfiguration
    • 本章源代码
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档