Spring Boot並不重複「造輪子」

2.1 Spring Boot簡介

Spring Boot是由Pivotal團隊提供的基於Spring的全新框架,其設計目的是簡化Spring應用的搭建和開發過程。該框架遵循「約定大於配置」原則,採用特定的方式進行配置,從而使開發者無須進行大量的XML配置。Spring Boot致力於成爲蓬勃發展的快速應用開發領域的領導者。html

Spring Boot並不重複「造輪子」,而是在原有Spring框架的基礎上進行封裝,而且它集成了一些類庫,用於簡化開發。換句話說,Spring Boot就是一個大容器。java

關於Spring Boot,其官網是這樣描述的:web

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can 「just run」.spring

We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.數據庫

從上面的描述中,咱們能夠了解到,Spring Boot帶給了咱們全新的應用部署方案,經過它能夠很方便地建立獨立的、生產級的基於Spring的應用程序。同時,經過Spring平臺和第三方庫能夠輕鬆構建視圖。apache

其實,Spring Boot默認集成了Tomcat,所以咱們能夠只編譯成jar包,經過Java命令啓動應用,大多數Spring Boot應用程序只須要不多的Spring配置。json

2.2 第一個Spring Boot工程

本節中,咱們將建立第一個Spring Boot工程,讀者能夠按照下面的步驟進行操做。api

(1) 打開IntelliJ IDEA,依次點擊File→New→Module,在彈出的對話框中選擇Maven,並點擊Next按鈕,建立一個Maven項目。這裏咱們在ArtifactId一欄中輸入demo-lesson-one,在GroupId一欄中輸入com.lynn.boot。建立好工程後,爲pom.xml增長如下內容:瀏覽器

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
複製代碼

其中,標籤聲明瞭Spring Boot的父項目,版本號定義爲2.0.3.RELEASE。咱們還能夠注意到,標籤中聲明瞭spring-boot-starter-web依賴,它提供了對Spring MVC的支持。tomcat

(2) 編寫應用啓動類Application:

package com.lynn.boot;

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

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
複製代碼

Spring Boot的強大之處在於能夠直接經過main方法啓動Web應用程序。在上述代碼中,咱們提供了應用程序的入口,經過調用SpringApplication.run()來啓動內置Web容器。咱們注意到,在Application類中添加了@SpringBootApplication註解,咱們將在2.4節中介紹它的做用。

默認狀況下,Spring Boot內置了Tomcat。固然,它還支持其餘容器,如Jetty。假若咱們要將默認容器改成Jetty,能夠將pom.xml文件修改爲下面這樣:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
複製代碼

在上述代碼中,咱們經過標籤將Tomcat的依賴包移除,並增長了Jetty的依賴包。

(3) 編寫控制器以驗證Spring Boot框架:

package com.lynn.boot.controller;

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

@RestController
public class HelloController {

    @RequestMapping(value = "hello")
    public String hello(){
       return "Hello World!";
    }
}
複製代碼

在上述代碼中,@RestController註解指示了該類爲控制器類,與它對應的註解是 @Controller。@RestController註解至關於 @Controller註解和@ResponseBody註解的結合。@RequestMapping註解的做用是定義一個HTTP請求地址,默認不限制請求方式,能夠是GET、POST亦或其餘方法,若是要限制請求方法,能夠在註解後面增長method屬性,如method=RequestMethod.GET表示只有GET請求才能調用該HTTP地址。

上面提到的註解均爲Spring MVC註解,咱們之因此可以在這裏很方便地使用Spring MVC註解,是由於第(1)步的依賴中添加了spring-boot-starter-web依賴,該依賴集成了Spring MVC。

(4) 運行Application類的main方法,並訪問localhost:8080/hello,便可看到如圖2-1所示的界面。

圖像說明文字

經過以上示例,咱們能夠知道:

 使用Spring Boot建立一個工程很是簡單,既沒有XML配置文件,也沒有Tomcat,經過幾個簡單的註解,運行main方法就能啓動一個Web應用;

 Spring Boot默認內置Tomcat;

 Spring Boot用註解代替了煩瑣的XML配置。

2.3 使用YAML文件配置屬性

在上一節中,咱們實現了一個最簡單的Web工程,沒有建立任何配置文件。固然,Spring Boot的任何配置均可以經過代碼實現。爲了便於擴展,它引入了PROPERTIES格式和YAML格式 的文件,能夠在其中定義一些經常使用屬性或自定義屬性。

2.3.1 YAML的基本用法

下面咱們先來看一下Spring Boot的通常配置,步驟以下。

(1) 在src/main/resources目錄下建立一個名爲application.yml的配置文件,並編寫如下內容:

server:
    servlet:
        #定義上下文路徑
        context-path: /demo
    #定義工程啓動的端口
    port: 8081複製代碼

在上述配置中,咱們經過server.servlet.context-path定義了應用的上下文路徑爲/demo,它的默認值爲/,server.port定義應用的啓動端口,其默認值爲8080,這裏設置爲8081。

(2) 啓動工程並訪問localhost:8081/demo/hello,就能夠看到如圖2-1所示的界面。

① 本書的全部示例都使用了YAML 栺式的配置文件。複製代碼

在2.2節中,咱們啓動工程時的監聽端口爲8080,上下文路徑爲/,可是咱們並無配置任何信息,那是由於全部配置屬性都有默認值,如端口的默認值爲8080。

接下來,咱們看一下YAML文件的結構,其基本格式爲:

key1:
    key2:
        key3: value複製代碼

咱們將它替換成properties的形式,即key1.key2.key3=value。固然,key的個數不是固定的。這裏須要說明的是,YAML格式很是嚴格。若是當前key後面須要跟value,則冒號後面必須至少有一個空格,不然編譯不會經過;其次,每一個子屬性之間須要經過空格或製表符(即按下Tab鍵)分隔,不然可能沒法正確取到屬性值。

若是咱們將上面例子中的YAML文件改爲如下形式:

server:
    servlet:
        context-path: /demo
    #冒號後面直接跟端口號
    port:8081複製代碼

那麼啓動工程後,控制檯會打印以下的報錯信息:

Caused by: org.yaml.snakeyaml.scanner.ScannerException: while scanning a simple key in 'reader', line 6, column 3:
    port:8081
    ^
could not find expected ':'
in 'reader', line 6, column 12:
    port:8081複製代碼

2.3.2 多環境配置

在一個企業級應用中,咱們可能開發時使用開發環境,測試時使用測試環境,上線時使用生產環境。每一個環境的配置都不同,好比開發環境的數據庫是本地地址,而測試環境的數據庫是測試地址。所以會遇到這樣一個問題:咱們在打包的時候,如何生成不一樣環境的包呢?

這裏的解決方案有不少,具體以下。

 每次編譯以前,手動把全部配置信息修改爲當前運行的環境信息。這種方式致使每次都須要修改,至關麻煩,也容易出錯。

 利用Maven,在pom.xml裏配置多個環境,每次編譯以前將settings.xml修改爲當前要編譯的環境ID。這種方式的缺點就是每次都須要手動指定環境,並且若是環境指定錯誤,發佈前是不知道的。

 建立多個針對不一樣環境的配置文件,經過啓動命令指定。這個方案就是本節重點介紹的,也是我強烈推薦的方式。

接下來,咱們看一下配置多環境的步驟。

(1) 將application.yml文件修改以下:

server:
    servlet: 
        context-path: /demo 
    port: 8081
spring:
    profiles:
        active: dev複製代碼

這裏經過spring.profiles.active指了明當前啓動的環境。

(2) 建立多環境配置文件,文件命名格式爲application-{profile}.yml,其中{profile}即爲上述配置將要指定的環境名,如新增名爲application-dev.yml的文件,咱們能夠在裏面添加配置:

server:
    port: 8080複製代碼

並將spring.profiles.active設置爲dev。

此時啓動工程,能夠看到工程的監聽端口已變爲8080。

你能夠繼續建立多環境文件,好比命名爲application-test.yml,將監聽端口改成8082,而後將spring.profiles.active改成test,再啓動工程觀察效果。在實際項目發佈的過程當中,不會手動修改spring.profiles.active的值,而是經過啓動命令來動態修改,具體細節見2.7節。

2.4 經常使用註解

前面提到過,Spring Boot主要是以註解形式代替煩瑣的XML配置。在這一節中,我將帶領你們瞭解一些經常使用註解的用法。

2.4.1 @SpringBootApplication

在前面的章節中,讀者是否注意到,Spring Boot支持main方法啓動。在咱們須要啓動的主類中加入註解 @SpringBootApplication,就能夠告訴Spring Boot這個類是工程的入口。若是不加這個註解,啓動就會報錯。讀者能夠嘗試去掉該註解,看一下效果。

查看 @SpringBootApplication註解的源碼,能夠發現該註解由 @SpringBootConfiguration、@EnableAutoConfiguration和 @ComponentScan組成。咱們能夠將 @SpringBootApplication替換爲以上3個註解,如:

package com.lynn.boot;

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

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
複製代碼

此時代碼的運行效果與2.2節一致。

2.4.2 @SpringBootConfiguration

加入了 @SpringBootConfiguration註解的類會被認爲是Spring Boot的配置類。咱們既能夠在application.yml中進行一些配置,也能夠經過代碼進行配置。

若是要經過代碼進行配置,就必須在這個類中添加 @SpringBootConfiguration註解。咱們既能夠在標註了這個註解的類中定義Bean,也能夠經過它用代碼動態改變application.yml的一些配置。例如,建立WebConfig類,並改變工程啓動的端口號:

package com.lynn.boot;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;

@SpringBootConfiguration
public class WebConfig implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        //給代碼設置應用啓動端口
        factory.setPort(8888);
    }
}
複製代碼

啓動工程,能夠看到監聽端口已經變成了8888。


說明:若是YAML配置文件和代碼配置了一樣的屬性,則會以代碼配置爲準。由於在Spring Boot應用啓動後,會先加載配置文件,而後再執行被 @SpringBootConfiguration標註的類,因此它會覆蓋配置文件配置的屬性。


此外,也可使用 @Configuration註解,它和 @SpringBootConfiguration的效果同樣,不過Spring Boot官方推薦採用 @SpringBootConfiguration註解。

2.4.3 @Bean

@Bean註解是方法級別的註解,主要添加在 @SpringBootConfiguration註解的類中,有時也添加在 @Component註解的類中。它的做用是定義一個Bean,相似於Spring XML配置文件的。

下面咱們就來看一下如何經過 @Bean註解注入一個普通類。

(1) 建立一個普通類Person,爲了便於測試,咱們爲該類增長了一個字段name:

package com.lynn.boot.bean;

public class Person {
    private String name;

    public void setName(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' + '}'; } } 複製代碼

(2) 在2.4.2節建立的WebConfig類中增長如下代碼:

@Bean
public Person person(){
    Person person = new Person();
    person.setName("lynn");
    return person;
}複製代碼

在上述代碼中,咱們經過一個 @Bean註解就能夠將Person對象加入Spring容器中,它簡化了傳統的Spring XML的方式。

(3) 進行單元測試。首先,添加單元測試依賴:

org.springframework.boot
spring-boot-starter-test
test
複製代碼

Spring Boot默認集成JUnit測試框架,經過添加spring-boot-starter-test依賴就能夠集成它。而後在src/main/test目錄下建立一個測試類,並編寫測試代碼:

package com.lynn.boot.test;

import com.lynn.boot.Application;
import com.lynn.boot.bean.Person;
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.SpringJUnit4ClassRunner;

@SpringBootTest(classes = Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MyTest {

    @Autowired
    private Person person;

    @Test
    public void test(){
        System.out.println(person);
    }
}
複製代碼

在上述代碼中,咱們添加 @SpringBootTest註解來指定入口類爲Application,再添加 @RunWith註解指定單元測試的運行環境爲SpringJUnit4ClassRunner,即便用JUnit4的單元測試框架,接着經過 @Autowired註解注入了Person類,最後經過test方法打印person信息。

注意:在test方法中須要添加 @Test註解才能啓用單元測試。

啓動單元測試時,能夠看到控制檯打印出瞭如下信息:

Person{name='lynn'}複製代碼

2.4.4 @Value

一般狀況下,咱們須要定義一些全局變量,此時想到的方法是定義一個public static常量並在須要時調用它。那麼是否有其餘更好的方案呢?答案是確定的,這就是本節要講的 @Value註解。

(1) 在application.yml裏自定義一個屬性data:

self:
    message:
        data: 這是我自定義的屬性複製代碼

上述配置不是Spring Boot內置屬性,而是咱們自定義的屬性。

(2) 修改HelloController類:

package com.lynn.boot.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Value("${self.message.data}")
    private String value;

    @RequestMapping(value = "hello",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String hello(){
        return value;
    }
}
複製代碼

其中,@Value註解的參數須要使用 ${} 將目標屬性包裝起來,該屬性既能夠是Spring內置的屬性,也能夠是自定義的屬性。


注意:若是返回的是String類型的值,那麼須要註明produces爲application/json而且charset=utf8,不然可能會出現亂碼;若是返回的是對象,則無須註明。由於Spring MVC不會對返回的String類型的值作任何處理,而若是返回對象的話,會執行Spring默認的JSON轉換器,它會處理編碼問題。


(3) 啓動工程並訪問localhost:8080/demo/hello,能夠看到如圖2-2所示的界面。

圖像說明文字


說明:@Value註解能夠獲取YAML文件的任何屬性值,它的好處以下:

 能夠經過啓動參數動態改變屬性值,而不用修改代碼;

 交給Spring統一管理常量,便於擴展和維護。

複製代碼複製代碼


2.5 Spring Boot集成模板引擎

在傳統的Spring MVC架構中,咱們通常將JSP、HTML頁面放到webapps目錄下。但Spring Boot沒有webapps,更沒有web.xml,若是要寫界面的話,該如何作呢?

咱們能夠集成模板引擎。Spring Boot官方提供了幾種模板引擎:FreeMarker、Velocity、Thymeleaf、Groovy、Mustache和JSP。本節中,咱們以FreeMarker爲例講解Spring Boot是如何集成模板引擎的。

首先,在pom.xml中添加對FreeMarker的依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>複製代碼

在resources目錄下創建static和templates兩個目錄,如圖2-3所示。其中static目錄用於存放靜態資源,譬如CSS、JavaScript和HTML等,templates目錄用於存放模板引擎文件。

圖像說明文字

而後在templates目錄下面建立index.ftl 文件,並添加以下內容:

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <h1>Hello World!</h1>
    </body>
</html>複製代碼

接着建立控制器類:

@Controller
public class PageController {

    @RequestMapping("index.html")
    public String index(){
        return "index";
    }
}
複製代碼
① freemarker 文件的默認後綴爲.ftl。複製代碼

最後,啓動Application.java,訪問localhost:8080/demo/index.html,就能夠看到如圖2-4所示的界面。

圖像說明文字

在上述代碼中,咱們要返回FreeMarker模板頁面,所以必須將其定義爲 @Controller,而不是前面定義的 @RestController。@RestController至關於 @Controller和 @ResponseBody的結合體。標註爲 @RestController註解時,SpringMVC的視圖解析器(ViewResolver)將不起做用,即沒法返回HTML或JSP頁面。ViewResolver的主要做用是把一個邏輯上的視圖名解析爲一個真正的視圖。當咱們將一個控制器標註爲 @Controller並返回一個視圖名時,ViewResolver會經過該視圖名找到實際的視圖,並呈現給客戶端。

2.6 更改默認的JSON轉換器

Spring Boot默認使用Jackson引擎去解析控制器返回的對象,該引擎在性能和便捷性上與第三方引擎(FastJson和Gson等)還有必定的差距,本節將介紹如何將默認轉換器替換爲FastJson轉換器。

(1) 在pom.xml中添加對FastJson的依賴:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>複製代碼

(2) 修改WebConfig類,爲其添加方法並設置FastJson轉換器:

@SpringBootConfiguration
public class WebConfig extends WebMvcConfigurationSupport{
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        FastJsonHttpMessageConverter fastConverter=new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig=new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.PrettyFormat
        );
        List<MediaType> mediaTypeList = new ArrayList<>();
        //設置編碼爲UTF-8
        mediaTypeList.add(MediaType.APPLICATION_JSON_UTF8);
        fastConverter.setSupportedMediaTypes(mediaTypeList);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
    }
}複製代碼

首先應繼承WebMvcConfigurationSupport類,該類提供了Spring Boot對Spring MVC的支持。而後重寫configureMessageConverters方法,該方法配置了消息轉換器。若是第三方框架但願處理Spring MVC中的請求和響應時,那麼須要實現HttpMessageConverter接口。而在上述代碼中,FastJsonHttpMessageConverter即是如此,它實現了HttpMessageConverter接口,並經過FastJsonConfig設置FastJson的處理參數,如經過MediaType設置編碼爲UTF-8,最後添加到HttpMessageConverter中。

這樣Spring MVC在處理響應時就能夠將JSON解析引擎替換爲FastJson。


說明:前面提到,若是控制器返回的是String類型的值,則須要顯式設置編碼。咱們替換成FastJson後,因爲已經設置了編碼,因此不管是字符串仍是對象,都無須設置編碼方式,讀者能夠試一試。


2.7 打包發佈到服務器上

Spring Boot支持使用jar和war兩種方式啓動應用,下面分別來介紹這兩種方式是怎麼啓動的。

2.7.1 使用內置Tomcat發佈jar包

因爲Spring Boot內置了Tomcat,咱們能夠將工程打包成jar,經過Java命令運行咱們的Web工程,具體步驟以下。

(1) 在pom.xml文件中添加如下內容:

<build>
    <finalName>api</finalName>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>      
         <mainClass>com.lynn.boot.Application</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <encoding>UTF-8</encoding>
                <useDefaultDelimiters>true</useDefaultDelimiters>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.18.1</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
 </build>複製代碼

在pom.xml中,<build>標籤訂義了關於Maven編譯和打包的一些信息。其中,<finalName>爲打包後的文件名,<plugins>設置了編譯的一些參數。Maven支持第三方插件,而Spring Boot的編譯插件就是spring-boot-maven-plugin,並經過<mainClass>指定了啓動類。後面maven-surefire-plugin就是Maven官方提供的用於構建測試用例的插件,若是有單元測試類,它在編譯完成後會執行單元測試,單元測試成功後纔會打包;若是不但願執行單元測試,那麼將<skipTests>設置爲true便可。我建議將設置爲true,若是設置爲false,會致使打包時間過長。若是單元測試類中存在對數據庫的增刪改測試,編譯時執行了它,可能會對原有數據形成影響。maven-compiler-plugin爲Maven官方提供的指定編譯器版本的插件,上述代碼中的1.8表示使用JDK 1.8版本編譯。

(2) 經過mvn clean package編譯並打包,如圖2-5所示。

圖像說明文字

(3) 將打包的內容上傳到服務器中,運行命令:

java -jar api.jar複製代碼

這樣就能啓動一個Spring Boot應用。前面提到,能夠經過命令參數來設置不一樣環境或者動態設置參數,那麼如何設置呢?下面以設置環境爲例,輸入命令:

java -jar api.jar --spring.profiles.active=dev複製代碼

應用啓動時,就會拉取application-dev.yml內的配置信息。若是你想改變任何屬性值,在--後面加上相應的屬性名和要改變的屬性值便可。

2.7.2 打包成war包發佈

除了編譯成jar包發佈外,Spring Boot也支持編譯成war包部署到Tomcat。

(1) 在pom.xml中將應用打包格式改爲war:

<packaging>war</packaging>複製代碼

這裏的就是告訴Maven,須要編譯成何種後綴的文件。

(2) 將標籤下的內容修改以下:

<build>
    <finalName>api</finalName>
    <resources>
        <resource>
             <directory>src/main/resources</directory>
             <filtering>true</filtering>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.18.1</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>複製代碼

上述內容和2.7.1節中的內容類似,增長了maven-resources-plugin插件,它用於編譯resources目錄下的文件。而在spring-boot-maven-plugin插件中無須指定<mainClass>,由於編譯後的war部署在外部Tomact上,它依託於Tomcat容器運行,不會執行main方法。

(3) 添加Tomcat依賴,將<scope>設置爲provided。這樣作的目的是編譯時去掉tomcat包,不然啓動時可能會報錯。咱們也不能直接經過<exclusion>標籤去掉tomcat包,由於在本地開發時,須要經過Application類啓動。相關代碼以下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>複製代碼

(4) 修改啓動類Application,它繼承了SpringBootServletInitializer類,並重寫了configure方法,以便Tomcat在啓動時能加載Spring Boot應用:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}
複製代碼

在上述代碼中,若是咱們是經過外部Tomcat啓動應用,則能夠去掉main方法。由於Tomcat在啓動時會執行configure方法,而configure方法會調用source方法並指定Application類,其做用與main方法一致。

(5) 使用mvn clean package編譯並打包成WAR格式的文件,而後將其複製到Tomcat中。啓動Tomcat,能夠看到應用可以被正常訪問。若是經過外部Tomcat啓動應用,則server.port指定的端口失效,轉而使用Tomcat設置的端口號。

經過war啓動程序沒法像jar包那樣,在啓動時指定運行環境或其餘想要動態改變的參數值,且上下文路徑以war包的名字爲準,還須要本身安裝Tomcat,比較麻煩,所以我推薦優先考慮jar包的啓動方式。


注意:若是以war方式部署多個Spring Boot工程到一個Tomcat下,可能會報錯,其緣由是Spring Boot的資源管理是默認打開的,而兩個項目同時使用會衝突。此時須要在每一個項目中增長如下配置:

spring:
    jvm:
       default-domain: api複製代碼

其中,在default-domain後面須要設置domain名,以保證每一個工程的domain不一致,這樣才能同時啓動多個工程。


2.8 WebFlux快速入門

Spring Boot 2.0爲咱們帶來了WebFlux,它採用Reactor做爲首選的流式框架,而且提供了對RxJava的支持。經過WebFlux,咱們能夠創建一個異步的、非阻塞的應用程序。接下來,咱們就一塊兒來領略WebFlux的風采。

(1) 建立一個基於Spring Boot的Maven工程,將其命名爲demo-lesson-one-webflux,而後在pom.xml文件中添加對WebFlux的依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>複製代碼

(2) 編寫一個Handler,用於包裝數據:

@Component
public class HelloHandler {

    public Mono<ServerResponse> hello(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
            .body(BodyInserters.fromObject("Hello, World!"));
    }
}
複製代碼

該類自定義了一個方法,該方法返回Mono 對象。這裏在ServerResponse的body方法中設置要返回的數據。

(3) 編寫接口類,即定義咱們一般所說的路由地址(接口地址):

@SpringBootConfiguration
public class HelloRouter {
    @Bean
    public RouterFunction<ServerResponse> routeHello(HelloHandler helloHandler) {
        return RouterFunctions.route(RequestPredicates.GET("/hello")
            .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), helloHandler::hello);
    }
}複製代碼
① Mono 是WebFlux 中屬於publisher(収布者)的類。在WebFlux 中,開収者的方法只需返回Mono 或Flux 類便可。複製代碼

由於路由須要註冊到Spring容器中,因此該類也須要添加 @SpringBootConfiguration註解,而將返回的路由標識爲一個Bean,這樣才能註冊到Spring容器中。

在上述代碼中,咱們定義一個方法routeHello而且返回了RouterFunction對象。在RouterFunction中,指定路由地址爲/hello,並指定Handler和對應的方法,即前面建立的HelloHandler。這樣經過路由地址/hello就能夠返回Handler的hello方法所設置的數據。

(4) 啓動Application.java並訪問地址localhost:8080/hello,能夠看到瀏覽器正常顯示HelloWorld。

經過控制檯,咱們能夠很清楚地看到它是經過NettyServer 啓動的:

Netty started on port(s): 8080複製代碼

這樣咱們就創建了一個路由地址。細心的讀者能夠發現,上述代碼過於煩瑣,Spring Boot也考慮到了這一點。爲了便於將MVC應用遷移到WebFlux,Spring Boot官方兼容了WebFlux和MVC,即咱們可使用MVC的註解來建立WebFlux的路由地址。

(1) 建立HelloController類並編寫如下代碼:

@RestController
public class HelloController {
    @RequestMapping(value = "hello")
    public Mono<String> hello(){
        return Mono.just("Hello World!");
    }
}複製代碼

能夠看到,上述代碼和前面編寫的代碼很類似,只是這裏咱們須要返回Mono對象,WebFlux將數據都包裝到Mono返回,經過調用just方法便可。just方法傳入的參數類型取決於Mono後面的泛型指定的類型。

(2) 啓動Application.java,咱們能夠獲得和前面代碼同樣的結果。


說明:若是咱們經過 @Controller和 @Router兩種方式定義了相同名字的路由地址,則會優先採用@Router方式。


① Netty 是一個異步的、事件驅動的網絡應用程序框架。複製代碼

2.9 小結

經過本章的學習,咱們瞭解了Spring Boot的基本用法並感覺到了YAML的優雅。本章涵蓋了一些實際項目中可能會用到的知識點,如經常使用註解、Spring Boot默認引擎的集成、JSON轉換器的更改以及編譯部署應用等。最後還介紹了目前較爲流行的WebFlux框架。在後面的內容中,咱們將進一步學習Spring Boot的其餘特性。

本文摘自《Spring Cloud實戰演練》

相關文章
相關標籤/搜索