Spring Boot Hello World的实现代码
本篇文章是springboot最入门的介绍。我们不借助任何额外的工具,从无到有创建一个spring boot的web项目,并运行这个项目。
项目构建
归根结底,spring boot就只是一个框架,几个jar而已,没什么神奇的。但使用spring initializr创建项目的过程把很多信息屏蔽掉了,这样我们就很难搞清楚spring boot的本质是什么。下面仅使用maven从无到有构建一个spring boot的web项目。
先创建一个maven空工程如下所示,项目的名字叫spring-boot-hello。
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.poype</groupid> <artifactid>spring-boot-hello</artifactid> <version>1.0-snapshot</version> <dependencies> </dependencies> </project>
现在这还是一个空的maven项目,我们可以在dependencies标签中添加我们需要的依赖,例如添加spring boot的依赖。但是spring boot为了减少配置,方便我们开发,提供了一个parent maven工程spring-boot-starter-parent,我们只要让我们的这个项目继承spring-boot-starter-parent工程,就能减少好多配置。修改我们的pom配置如下:
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.poype</groupid> <artifactid>spring-boot-hello</artifactid> <version>1.0-snapshot</version> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.1.4.release</version> </parent> <dependencies> </dependencies> </project>
目前我们的这个maven项目还没有导入任何dependency,这点可以通过执行mvn dependency:tree
命令确定。
我们要创建的是一个web项目,所以添加spring-boot-starter-web这个依赖。修改pom配置如下:
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.poype</groupid> <artifactid>spring-boot-hello</artifactid> <version>1.0-snapshot</version> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.1.4.release</version> </parent> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> </dependencies> </project>
由于在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配置如下:
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.poype</groupid> <artifactid>spring-boot-hello</artifactid> <version>1.0-snapshot</version> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.1.4.release</version> </parent> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> </dependencies> <build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </build> </project>
接着我们执行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方法的类。spring-boot-classes是应用自己类的路径,spring-boot-lib是应用依赖的第三方包的路径。
看到这里我们可以大概总结一下(仅仅是yy,目前理解还不够深入),spring boot实现了一套自己的部署路径规范(应用自己的类放在哪里,应用依赖的第三方jar放在哪里等等),就像j2ee规范一样。然后利用tomcat的jar实现servlet容器的功能,对web请求进行处理。
可以说spring boot利用tomcat打造了一个全新的平台,这个平台也仅仅只在servlet容器部分利用到了tomcat的功能,至于部署规范和加载机制,都是spring boot自己全新实现的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: java遍历机制性能的比较详解
推荐阅读
-
Spring Boot Hello World的实现代码
-
Spring Boot实现模块化的几种方法
-
C#学习进阶Hello World的17种写法代码分享
-
详解Spring Boot 定时任务的实现方法
-
spring-boot集成spring-security的oauth2实现github登录网站的示例
-
Spring MVC的国际化实现代码
-
Spring Data JPA 实现多表关联查询的示例代码
-
Spring Boot中使用 Spring Security 构建权限系统的示例代码
-
spring boot实现软删除的示例代码
-
spring boot 项目利用Jenkins实现自动化部署的教程详解