1. 程式人生 > >為什麼下一個5年java後臺開發你該選擇Spring Boot?

為什麼下一個5年java後臺開發你該選擇Spring Boot?

我們先來看看以前我們是怎麼寫Spring的

以前的Spring

整合複雜

相信大家學SSM(Spring+Spring MVC+MyBatis)結構的時候, 最痛苦的莫過於整合了.. 
既然要整合三者, 那麼需要做哪些配置呢?

  1. 選擇各種依賴的版本,spring核心的lib: spring-core, spring-context, spring-beans, spring-context-support, spring-aop. spring mvc相關的lib: spring-web,spring-webmvc; 資料庫相關的模組: mysql-connector-java, mybatis, mybatis-spring. log相關模組slf4j-api, slf4j-log4j12. json處理模組jackson, 資料庫連線池commons-dbcp..等..(要自己選版本, 注意相容性問題)
  2. 配置spring的xml: 配置自動掃描, 配置datasource, 配置spring和mybatis的整合的SqlSessionFactoryBean, 配置mybatis掃描的MapperScannerConfigurer. 配置事務管理器.
  3. 配置spring mvc的xml: 配置annotation-driven, 配置自動掃描Controller(有遇到過因為兩個容器重複掃描導致事務註解失效的問題嗎?), 配置InternalResourceViewResolver.
  4. 因為跑在tomcat裡面, 所以需要配置web.xml, 來啟動spring, 且需要配置DispatchServlet, 將所有的請求轉發給spring mvc.

大概經過一天的配置, 終於可以開始寫程式碼了…

試錯成本高

如果這作為主工程倒還好, 配一次以後就不需要弄了. 
但是這對於想要學習Spring的特性的人(比如Spring MVC的引數對映, Spring的事務機制, Spring Data等), 以及想嘗試Spring, 或者想快速開發新服務的人(比如微服務), 都非常的不友好. 從有想法去要做, 到真正開始做我想做的事, 好幾個小時就過去了, 試錯成本太大, 完全沒有心思去嘗試了.

配置複雜, 歷史版本多

更痛苦的是對於初學程式設計師甚至一些有經驗的程式設計師, Spring從03年開始到17年, 10多年的發展歷程, xml, 註解, java config好幾種風格的配置糾纏一起, 分不清哪些配置是推薦的, 哪些配置是有用的, 哪些配置是不被推薦了的, 哪些配置是廢棄了的, 哪些配置間是衝突的 …

預設配置

用久了Spring, 你會發現, 很多東西都其實應該有預設配置的.

  1. 一般我們都要去指定spring和spring mvc的配置檔案地址…為什麼不直接告訴我們, 用的是application.properties就好了..不想用這個的話, 那就自己再去改吧.
  2. 比如用了Spring 3.X以後的版本, 基本都會開啟註解掃描, 既然大家都開啟, 那麼預設開啟就好了. 為什麼還要自己去要搜尋, 如何開啟註解, 網路上各種亂七八糟的配置.
  3. 比如我用了mysql, 不管是JPA, MyBatis還是JdbcTemplate, 基本都會配置對應的事務管理器..既然這樣, 為什麼框架不自動幫我配置對應的事務管理器.
  4. 比如我用了Spring MVC, 一般我都不在意資原始檔位置如何, 直接給我生成一個預設的資料夾, 我把資原始檔放進去就好了. 省得我自己去設定一個mvc:resources標籤. 
    等等..

也就是說, 你會發現你做的那些整合配置, 幾乎在所有的新專案中, 都不需要改動, 既然這些配置都可以預設, 那麼為什麼還需要我們去寫!!!

Spring Boot !!!

https://start.spring.io/, 選擇web, 然後再用ide開啟這個工程. 
或者像下面一樣, 自己新建一個maven工程, 然後新增以下依賴到pom.xml中.

<?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.haoyifen</groupId>
    <artifactId>actuator</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>actuator</name>
    <description>Demo project for Spring Boot Actuator</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

寫一個java檔案, hello/SampleController.java

package hello;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@Controller
@SpringBootApplication
public class SampleController {

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

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SampleController.class, args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

直接執行這個類的main方法…在瀏覽器中訪問http://localhost:8080, 就可以看到激動人心的Hello World了! 
一個基於Spring MVC的web應用demo就完成了. 
不需要自己選擇各種依賴版本, 不需要配置DispatchServlet, .不需要tomcat, 不需要部署到tomcat..只需要簡單的程式碼, 直接執行main方法就好了.

Spring Boot如何解決這幾個問題

前面我們提到的以前寫Spring時, 有幾個比較煩的問題. 
1. 依賴太多了, 且存在版本問題 
2. 配置太多了且每次都一樣, 大部分工程, 配置每次都是一樣的, 從一個地方拷貝到另外一個地方. 且Spring發展10多年, 各種配置版本太多, 對於很多程式設計師來說, 分不清哪個是有效, 哪個無效. 
3. 部署太麻煩. 需要tomcat部署, 專案結構也需要照著java ee的目錄結構來寫.

魔法

dependencyManagement:

我們可以看到上面的pom.xml檔案中. 指定了我們的模組父project是spring-boot-starter-parent.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我們可以看到上面的pom.xml依賴型別是spring-boot-starter-*, 以spring-boot-starter-web為例. 不需要指定version, 通過父工程的dependencyManagement來獲得其版本為1.5.3. spring-boot-starter-web本身的pom.xml檔案中有引用到以下的lib, 且paretn也為1.5.3版本, 然後通過maven的依賴傳遞, spring-boot-starter-web會為該工程引入1.5.3版本的spring-boot-starters對應的spring-boot和spring mvc模組.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starters</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
    </dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

這樣就完成了依賴的管理.

EnableAutoConfiguration

前面SampleController類上有SpringBootApplication註解, 這個註解上面又有EnableAutoConfiguration註解. 自動配置預設的配置就是由這個註解生效的. 你如果添加了spring-boot-starter-web依賴, 那麼就給你配置一堆和Spring MVC相關的預設配置, 如果你添加了spring-boot-starter-jdbc,那麼就給你自動配置jdbcTemplate和事務管理器. 如果你添加了spring-boot-starter-mongodb, 那麼就給你自動配置mongodbTemplate等等..

大概原理舉例說明: 
比如我們添加了spring-boot-starter-jdbc依賴, 那麼類路徑下就會有JdbcTemplate這個類. 
Spring Boot自動配置檢測classpath有jdbcTemplate這個類, 且beanFactory中沒有JdbcTemplate的bean, 也就是說沒有手動配置, 就從BeanFactory中取出我們配置的datasource, 然後自動配置一個JdbcTemplate. 然後對於事務管理器也是相應的邏輯. 配置一個事務管理器的bean. 
相關程式碼可見JdbcTemplateAutoConfiguration和DataSourceTransactionManagerAutoConfiguration. 
Spring Boot通過自動配置的魔法, 大大減少了Spring的配置.

嵌入式tomcat和Spring Boot自定義的FatJar

之前的Spring Web應用都是根據java ee的專案結構來寫, 打包成War格式, 然後部署到tomcat中, 十分的麻煩. 
Spring Boot可以使用內嵌的Tomcat, 由我們的main方法來啟動Spring, 接著啟動Tomcat, 而不是由Tomcat來啟動Spring. 
EmbeddedServletContainerAutoConfiguration會進行Tomcat的配置, 由TomcatEmbeddedServletContainer進行啟動. 
在本地開發時, 直接和普通java程式一樣, 使用main方法啟動. 
Spring Boot應用可以直接由maven的plugin打包成其定義的FatJar內容的jar包, 在部署時, 直接使用java -jar application.jar進行啟動, 部署十分方便.

總結

Spring是一個無所不包的一站式java開發平臺. 但由於10多年的發展, Spring的體系太過龐大, 程式設計師無法掌握其歷史, 同時複雜的依賴, 大量的配置, 複雜的部署給開發帶來了很大的阻礙. 
Spring Boot基於約定大於配置的理念, 簡化了依賴管理, 簡化了配置, 簡化了部署. 大大降低了使用Spring開發的難度, 大大加快了開發速度. 我認為必將是Java後臺開發下一個5年的殺手級框架.