资讯专栏INFORMATION COLUMN

Spring Boot Hello World

lijinke666 / 1559人阅读

摘要:现在这还是一个空的项目,我们可以在标签中添加我们需要的依赖,例如添加的依赖。修改我们的配置如下目前我们的这个项目还没有导入任何,这点可以通过执行命令确定。

本篇文章是SpringBoot最入门的介绍。我们不借助任何额外的工具,从无到有创建一个Spring Boot的web项目,并运行这个项目。

项目构建

归根结底,Spring Boot就只是一个框架,几个jar而已,没什么神奇的。但使用Spring Initializr创建项目的过程把很多信息屏蔽掉了,这样我们就很难搞清楚Spring Boot的本质是什么。下面仅使用maven从无到有构建一个Spring Boot的web项目。
先创建一个maven空工程如下所示,项目的名字叫spring-boot-hello。



    4.0.0

    com.poype
    spring-boot-hello
    1.0-SNAPSHOT

    
        
    

现在这还是一个空的maven项目,我们可以在dependencies标签中添加我们需要的依赖,例如添加Spring Boot的依赖。但是Spring Boot为了减少配置,方便我们开发,提供了一个parent maven工程spring-boot-starter-parent,我们只要让我们的这个项目继承spring-boot-starter-parent工程,就能减少好多配置。修改我们的POM配置如下:



    4.0.0

    com.poype
    spring-boot-hello
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
    

    
       
    

目前我们的这个maven项目还没有导入任何dependency,这点可以通过执行mvn dependency:tree命令确定。
我们要创建的是一个web项目,所以添加spring-boot-starter-web这个依赖。修改POM配置如下:



    4.0.0

    com.poype
    spring-boot-hello
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
    

由于在spring-boot-starter-parent的dependencyManagement中已经用声明了spring-boot-starter-web,所以此处我们可以省略它的version配置。
再次执行mvn dependency:tree命令获得如下结果:

[INFO] Scanning for projects...
[INFO] 
[INFO] --------------------< com.poype:spring-boot-hello >---------------------
[INFO] Building spring-boot-hello 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ spring-boot-hello ---
[INFO] com.poype:spring-boot-hello:jar:1.0-SNAPSHOT
[INFO] - org.springframework.boot:spring-boot-starter-web:jar:2.1.4.RELEASE:compile
[INFO]    +- org.springframework.boot:spring-boot-starter:jar:2.1.4.RELEASE:compile
[INFO]    |  +- org.springframework.boot:spring-boot:jar:2.1.4.RELEASE:compile
[INFO]    |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.4.RELEASE:compile
[INFO]    |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.4.RELEASE:compile
[INFO]    |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO]    |  |  |  +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO]    |  |  |  - org.slf4j:slf4j-api:jar:1.7.26:compile
[INFO]    |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.2:compile
[INFO]    |  |  |  - org.apache.logging.log4j:log4j-api:jar:2.11.2:compile
[INFO]    |  |  - org.slf4j:jul-to-slf4j:jar:1.7.26:compile
[INFO]    |  +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO]    |  +- org.springframework:spring-core:jar:5.1.6.RELEASE:compile
[INFO]    |  |  - org.springframework:spring-jcl:jar:5.1.6.RELEASE:compile
[INFO]    |  - org.yaml:snakeyaml:jar:1.23:runtime
[INFO]    +- org.springframework.boot:spring-boot-starter-json:jar:2.1.4.RELEASE:compile
[INFO]    |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO]    |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO]    |  |  - com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
[INFO]    |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.8:compile
[INFO]    |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.8:compile
[INFO]    |  - com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.8:compile
[INFO]    +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.1.4.RELEASE:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.17:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.17:compile
[INFO]    |  - org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.17:compile
[INFO]    +- org.hibernate.validator:hibernate-validator:jar:6.0.16.Final:compile
[INFO]    |  +- javax.validation:validation-api:jar:2.0.1.Final:compile
[INFO]    |  +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile
[INFO]    |  - com.fasterxml:classmate:jar:1.4.0:compile
[INFO]    +- org.springframework:spring-web:jar:5.1.6.RELEASE:compile
[INFO]    |  - org.springframework:spring-beans:jar:5.1.6.RELEASE:compile
[INFO]    - org.springframework:spring-webmvc:jar:5.1.6.RELEASE:compile
[INFO]       +- org.springframework:spring-aop:jar:5.1.6.RELEASE:compile
[INFO]       +- org.springframework:spring-context:jar:5.1.6.RELEASE:compile
[INFO]       - org.springframework:spring-expression:jar:5.1.6.RELEASE:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.018 s
[INFO] Finished at: 2019-05-19T22:54:50+08:00
[INFO] ------------------------------------------------------------------------

可以看到在添加spring-boot-starter-web这个依赖后,有许多的jar都被导入了。
除了更多的spring-boot-starter-*被导入了之外,更重要的是很多Spring Framework的jar也被导入了,包括spring-core、spring-beans、spring-context、spring-aop等等。另外还有与tomcat相关的jar也被导入了,也就是说现在我们已经有了可以运行web程序的servlet容器了。
工程配置已经完成,新建一个HelloController测试类,输入如下代码:

package com.poype.springboot.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@EnableAutoConfiguration
public class HelloController {

    @RequestMapping("/hello")
    String home() {
        return "Hello World!";
    }

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

现在,我们已经完成了一个简单的web应用开发,可以启动我们这个应用了。
由于我们的工程继承了spring-boot-starter-parent的POM配置,它提供了启动spring-boot应用的相关插件(该插件的run目标用于启动应用),可以通过执行mvn spring-boot:run命令启动应用,得到如下运行结果。

从运行结果中可以看到,spring-boot启动了Tomcat服务器,并监听在8080端口。下面我们打开浏览器,输入地址http://localhost:8080/hello就可以看到程序运行结果。

应用打包

应用构建好之后,需要build出一个应用包才能用于生产部署。为此需要在POM配置中新增一个插件,修改POM配置如下:



    4.0.0

    com.poype
    spring-boot-hello
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

接着我们执行mvn clean package命令,可以在target目录下发现构建好的应用包 spring-boot-hello-1.0-SNAPSHOT.jar
执行java -jar ./target/spring-boot-hello-1.0-SNAPSHOT.jar命令就可以启动应用了。

Spring Boot是怎么做到的

上面的例子虽然非常简单,但却也是一个标准的spring web应用。我们可以回忆一下,如果没有Spring Boot,创建一个这样的web应用都需要哪些步骤呢?首先要在maven的POM中导入N多相关dependency(包括Spring的、servlet的、json的...)。然后添加各种复杂配置(包括servlet的、Spring的、Spring MVC的...)。最后写完代码build好一个war包,我们还需要下载一个Tomcat,并将war包放到tomcat下的指定路径,启动tomcat部署应用。这个过程即使是工作几年的老司机,从无到有创建一个项目估计也要十几分钟,如果是新手再遇到一些问题,解决起来就更麻烦了,可能几个小时也不一定能搞得出来。
使用Spring Boot构建应用,即便我们仅仅使用maven,也几乎没有什么配置。如果使用Spring Initializr的话,创建好工程无需任何配置就直接可以写代码了,非常的方便,即使是新手几分钟也能搞出来这个HelloWorld应用。这就是Spring Boot给我的最初印象,但是它是如何做到这些的呢?

约定大于配置

Spring Boot提供了很多Starter依赖,每种类型的Starter提供了这种类型应用可能需要的一系列dependency(利用maven间接依赖的特性)。例如我们这里创建的是一个web应用,所以我们的项目依赖spring-boot-starter-web,而spring-boot-starter-web会将web开发可能需要的依赖全部帮我们导入,省去很多配置的工作。spring-boot-starter-parent是一个特殊的starter,它提供了许多maven默认配置,如dependenceManagment。
另一个比较重要的是注解@EnableAutoConfiguration,Spring Boot看到这个注解,会根据已经加入的jar dependency执行相关的配置。例如在我们的工程中有Spring MVC和Tomcat的依赖,Spring Boot就会猜到这是一个WEB工程,它就会对项目执行相应的配置(如Spring MVC和Servlet的配置)。

应用启动

Spring Boot自带了一个Tomcat容器,省去我们自己安装和配置容器的工作。为了了解Spring Boot的启动过程,我们将build好的jar解压得到的目录结构如下图所示:

其中最主要的配置文件是MANIFEST.MF,在执行java -jar *.jar启动命令时,JVM参考的就是这个文件的配置。其文件内容如下:

Manifest-Version: 1.0
Implementation-Title: spring-boot-hello
Implementation-Version: 1.0-SNAPSHOT
Built-By: poype
Implementation-Vendor-Id: com.poype
Spring-Boot-Version: 2.1.4.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.poype.springboot.web.HelloController
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.6.1
Build-Jdk: 1.8.0_211
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
 ot-starter-parent/spring-boot-hello

Main-Class是jar包中的启动类,可以看到是一个叫org.springframework.boot.loader.JarLauncher类,是Spring Boot提供的Launcher类。Start-Class是我们自己编写的含有main方法的类。JarLauncher的代码如下:

public class JarLauncher extends ExecutableArchiveLauncher {
    static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";

    static final String BOOT_INF_LIB = "BOOT-INF/lib/";

    public JarLauncher() {}

    protected JarLauncher(Archive archive) {
        super(archive);
    }

    @Override
    protected boolean isNestedArchive(Archive.Entry entry) {
        if (entry.isDirectory()) {
            return entry.getName().equals(BOOT_INF_CLASSES);
        }
        return entry.getName().startsWith(BOOT_INF_LIB);
    }

    public static void main(String[] args) throws Exception {
        new JarLauncher().launch(args);
    }
}

从代码中可以看出,BOOT-INF/classes/路径下存放了应用程序自己的类,BOOT-INF/lib/路径下存放了第三方依赖的jar,包括内嵌的tomcat jar。
由于这个Jar中既包含应用程序自己的类,又包含应用所依赖的第三方的Jar,还包含Spring Boot Loader相关的类,所以这个Jar被称作Fat Jar。
在JarLauncher类的main函数中,通过launch方法启动整个应用。launch方法的实现在父类Launcher中。在Launcher方法中,会根据MANIFEST.MF中Start-Class的配置项找到我们自己的Main Class,然后构造一个ClassLoader加载应用类和第三方的Jar,最后会创建一个新的线程执行应用程序自己的main函数。
看到这里我们可以大概总结一下,Spring Boot实现了一套自己的部署路径规范(应用自己的类放在哪里,应用依赖的第三方jar放在哪里等等),就像J2EE规范一样。然后利用tomcat的jar实现servlet容器的功能,对WEB请求进行处理。
可以说Spring Boot利用tomcat打造了一个全新的平台,这个平台也仅仅只在servlet容器部分利用到了tomcat的功能,至于部署规范和加载机制,都是Spring Boot自己全新实现的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74541.html

相关文章

  • Spring Boot [Hello World]

    摘要:默认使用了内嵌容器支持开箱即用。备注关于第三步注解的一些描述该注解是引入的。查看源码可知其包含了和注解。我们可以将其看做对注解的增强与细分常用来返回格式的数据。 导读: 通过上篇文章, 我们已经了解到了 Spring Boot 作为一个Spring的脚手架, 其核心思想便是约定大于配置,通过一层层的封装让我们可以在最短的时间内搭建一个web项目,从繁琐的配置中走出来更加关注业务代码。...

    OnlyMyRailgun 评论0 收藏0
  • spring-boot创建最简单的web应用

    摘要:初衷看了一下相关的书籍,创建一个的应用,是那么的简单。首先,我们只是创建一个简单的并不打算使用默认的,而是使用传统的。在下创建目录并且在目录下新建,内容为页面。如果是在内置的的情况下,应用会自动重启。 初衷 看了一下spring-boot相关的书籍,创建一个hello world!的应用,是那么的简单。然而,自己动手,却很不一样。 首先,我们只是创建一个简单的hello world!并...

    xiaolinbang 评论0 收藏0
  • 【从零入门系列-0】Spring BootHello World

    摘要:结束语非常智能化,为开发者提供大量的默认配置细节,因此在的帮助下可以快速完成项目的运行,极简入门继续看从零入门系列程序结构设计说明 环境准备 java 开发环境 JDK1.8 安装 Maven 安装,jar自动依赖及包管理工具 IDE编辑器:IntelliJ IDEA 2019 说明 本项目为从零入门示例,目标为构建一个书籍增删改查管理页,力争记录一个无java基础的程序员学习笔...

    icyfire 评论0 收藏0
  • SpringBoot 2.X Kotlin 系列之Hello World

    摘要:二教程环境三创建项目创建项目有两种方式一种是在官网上创建二是在上创建如图所示勾选然后点,然后一直默认最后点击完成即可。我们这里看到和普通的接口没有异同,除了返回类型是用包装之外。与之对应的还有,这个后面我们会讲到。 showImg(https://segmentfault.com/img/remote/1460000018819338?w=1024&h=500); 从去年开始就开始学习...

    warkiz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<