學習Spring Boot

spring_logo.png

Spring boot 是什么 ?

簡單說, spring boot 是一個構(gòu)建項目的工具, 一個腳手架.

Spring boot 能干什么?

spring boot 做非常少的配置就可以構(gòu)建生產(chǎn)級別的單體應用.

Spring boot 怎么干的?

下面讓我們來用spring boot 做一個hello world.

  1. 環(huán)境準備, 需要保證你的機器上已經(jīng)有了如下軟件

    • JDK1.8+
    • gradle4+
  2. 創(chuàng)建項目目錄, 假設(shè)這個新的項目叫apple.

    $ cd /tmp
    $ mkdir apple
    
  3. 創(chuàng)建gradle配置文件,在這個目錄下創(chuàng)建build.gradle文件.

    $ cd apple
    $ vi build.gradle
    

    將如下代碼復制到build.gradle文件中.

    plugins {
        id 'org.springframework.boot' version '2.0.1.RELEASE'
    }
    
    apply plugin: 'java'
    apply plugin: 'io.spring.dependency-management'
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile 'org.springframework.boot:spring-boot-starter-web'
        testCompile 'org.springframework.boot:spring-boot-starter-test'
        testCompile 'org.springframework.boot:spring-boot-starter-webflux'
    }
    
    bootRun {
        main = 'com.thoughtworks.apple.Launcher'
    }
    
  4. 寫一個Hello world.

    • 按照如下目錄結(jié)構(gòu)初始化項目內(nèi)容
    apple
      \-src
         \-main
           \-java
              \-com.thoughtworks.apple
                  |-controller
                  |   \-HomeController.java
                  \-Launcher.java              
    
    • HomeController.java內(nèi)容如下
    package com.thoughtworks.apple.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HomeController {
        @RequestMapping("/")
        String home() {
            return "Hello World!";
        }
    }
    
    
    • Launcher.java內(nèi)容如下
    package com.thoughtworks.apple;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.context.annotation.ComponentScan;
    
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan("com.thoughtworks.apple")
    public class Launcher {
        public static void main(String[] args) {
            SpringApplication.run(Launcher.class, args);
        }
    }
    
    
  5. 運行

    執(zhí)行命令gradle bootRun啟動應用,之后會打印如下日志:

    $ gradle bootRun
    
    > Task :bootRun
    
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::        (v2.0.1.RELEASE)
    
    2018-05-05 10:23:41.383  INFO 38941 --- [           main] com.thoughtworks.apple.Launcher          : Starting Launcher on CNyfqi.local with PID 38941 (/private/tmp/apple/build/classes/java/main started by yfqi in /private/tmp/apple)
    2018-05-05 10:23:41.386  INFO 38941 --- [           main] com.thoughtworks.apple.Launcher          : No active profile set, falling back to default profiles: default
    2018-05-05 10:23:41.432  INFO 38941 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@3b2c72c2: startup date [Sat May 05 10:23:41 CST 2018]; root of context hierarchy
    2018-05-05 10:23:42.289  INFO 38941 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2018-05-05 10:23:42.313  INFO 38941 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2018-05-05 10:23:42.313  INFO 38941 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.29
    2018-05-05 10:23:42.323  INFO 38941 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/yfqi/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
    2018-05-05 10:23:42.402  INFO 38941 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2018-05-05 10:23:42.403  INFO 38941 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 973 ms
    2018-05-05 10:23:42.522  INFO 38941 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
    2018-05-05 10:23:42.525  INFO 38941 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
    2018-05-05 10:23:42.526  INFO 38941 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
    2018-05-05 10:23:42.526  INFO 38941 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
    2018-05-05 10:23:42.526  INFO 38941 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
    2018-05-05 10:23:42.627  INFO 38941 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2018-05-05 10:23:42.809  INFO 38941 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@3b2c72c2: startup date [Sat May 05 10:23:41 CST 2018]; root of context hierarchy
    2018-05-05 10:23:42.878  INFO 38941 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto java.lang.String com.thoughtworks.apple.controller.HomeController.home()
    2018-05-05 10:23:42.884  INFO 38941 --- [           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.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
    2018-05-05 10:23:42.885  INFO 38941 --- [           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.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
    2018-05-05 10:23:42.910  INFO 38941 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2018-05-05 10:23:42.910  INFO 38941 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2018-05-05 10:23:43.048  INFO 38941 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
    2018-05-05 10:23:43.100  INFO 38941 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2018-05-05 10:23:43.105  INFO 38941 --- [           main] com.thoughtworks.apple.Launcher          : Started Launcher in 2.148 seconds (JVM running for 2.523)
    2018-05-05 10:24:03.416  INFO 38941 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
    2018-05-05 10:24:03.416  INFO 38941 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
    2018-05-05 10:24:03.436  INFO 38941 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 20 ms
    <=========----> 75% EXECUTING [1m 28s]
    > :bootRun
    

    之后在瀏覽器中訪問http://localhost:8080/ 能看到如下頁面說明程序運行成功了.
    [圖片上傳失敗...(image-e28268-1529483896366)]

進階

如何將gradle命令引入項目

當我們本地有多個項目, 且每個項目的gradle版本不一樣時, 我們就需要把gradle命令保存在項目內(nèi), 然后每個項目用自己的gradle來構(gòu)建. 下面這個命令可以直接初始化引入一個gradle命令到項目內(nèi)部.

$ gradle wrapper --gradle-version 4.0

之后項目目錄下會多出四個文件

drwxr-xr-x   4 yfqi  wheel   128 May  5 10:49 .gradle
drwxr-xr-x   3 yfqi  wheel    96 May  5 10:49 gradle
-rwxr-xr-x   1 yfqi  wheel  5296 May  5 10:49 gradlew
-rw-r--r--   1 yfqi  wheel  2260 May  5 10:49 gradlew.bat

以后就可以在項目根目錄下執(zhí)行 ./gradlew來運行g(shù)radle的tasks了.

測試Hello World

程序成功運行了, 讓我們來寫一個測試用例測試一下hello world.

  • 測試目錄結(jié)構(gòu)如下

    apple
      \-src
         |-main   
         \-test
            \-java
                \-com.thoughtworks.apple.controller
                   \-HomeControllerTest.java       
    
  • HomeControllerTest.java內(nèi)容如下

    package com.thoughtworks.apple.controller;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.reactive.server.WebTestClient;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class HomeControllerTest {
        @Autowired
        private WebTestClient webClient;
    
        @Test
        public void should_get_home() {
            this.webClient.get().uri("/").exchange()
                    .expectStatus().isOk()
                    .expectBody(String.class).isEqualTo("Hello World!");
        }
    }
    
  • 運行測試使用命令./gradlew test能看到如下日志說明測試執(zhí)行成功

    $ gradle test
    Starting a Gradle Daemon (subsequent builds will be faster)
    
    > Task :test
    2018-05-05 10:36:18.034  INFO 39291 --- [       Thread-6] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@918accb: startup date [Sat May 05 10:36:15 CST 2018]; root of context hierarchy
    
    
    BUILD SUCCESSFUL in 12s
    3 actionable tasks: 3 executed
    

打包部署

  1. 執(zhí)行命令./grdlew bootJar來打包spring boot項目. 命令執(zhí)行成功后會在apple/build/libs下多出一個jar包apple.jar.這就打包成功了.
  2. 把打包好的jar包復制到運行的服務器, 執(zhí)行命令java -jar apple.jar &就可以把應用啟動起來.

Spring Boot Starters

上面的例子大家會發(fā)現(xiàn)項目只是依賴了三個Spring Boot的Starter就完成了對所有第三方jar包的引用.Starter其實就是對第三方jar包依賴按照業(yè)務需要做了一個聚合,Spring Boot提供了大量的Starter來幫助開發(fā)人員快速開始構(gòu)建項目, 降低了開發(fā)人員調(diào)包依賴的工作量.在這兩個地址可以查看Spring Boot的所有的Starters.

源碼

文章的完整代碼可以在這里找到: https://github.com/qyf404/learning-spring-boot

作者:辵鵵

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市陪每,隨后出現(xiàn)的幾起案子适贸,更是在濱河造成了極大的恐慌蜕青,老刑警劉巖择份,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異象颖,居然都是意外死亡布疙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門辆床,熙熙樓的掌柜王于貴愁眉苦臉地迎上來佳晶,“玉大人,你說我怎么就攤上這事讼载〗窝恚” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵咨堤,是天一觀的道長菇篡。 經(jīng)常有香客問我,道長一喘,這世上最難降的妖魔是什么逸贾? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上铝侵,老公的妹妹穿的比我還像新娘灼伤。我一直安慰自己,他們只是感情好咪鲜,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布狐赡。 她就那樣靜靜地躺著,像睡著了一般疟丙。 火紅的嫁衣襯著肌膚如雪颖侄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天享郊,我揣著相機與錄音览祖,去河邊找鬼。 笑死炊琉,一個胖子當著我的面吹牛展蒂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播苔咪,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锰悼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了团赏?” 一聲冷哼從身側(cè)響起箕般,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舔清,沒想到半個月后丝里,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡体谒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年丙者,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片营密。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖目锭,靈堂內(nèi)的尸體忽然破棺而出评汰,到底是詐尸還是另有隱情,我是刑警寧澤痢虹,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布被去,位于F島的核電站,受9級特大地震影響奖唯,放射性物質(zhì)發(fā)生泄漏惨缆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坯墨。 院中可真熱鬧寂汇,春花似錦、人聲如沸捣染。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耍攘。三九已至榕栏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蕾各,已是汗流浹背扒磁。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留式曲,地道東北人妨托。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像检访,于是被迫代替她去往敵國和親始鱼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容