背景
從Servlet技術到Spring和Spring MVC,開發Web應用變得越來越簡捷。但是Spring和Spring MVC的眾多配置有時卻讓人望而卻步,相信有過Spring MVC開發經驗的朋友能深刻體會到這一痛苦。因為即使是開發一個Hello-World的Web應用,都需要我們在pom檔案中匯入各種依賴,編寫web.xml、spring.xml、springmvc.xml配置檔案等。特別是需要匯入大量的jar包依賴時,我們需要在網上查詢各種jar包資源,各個jar間可能存在著各種依賴關係,這時候又得下載其依賴的jar包,有時候jar包間還存在著嚴格的版本要求,,所以當我們只是想開發一個Hello-World的超簡單的Web應用時,卻把極大部分的時間在花在了編寫配置檔案和匯入jar包依賴上,極大地影響了我們的開發效率。所以為了簡化Spring繁雜的配置,Spring Boot應運而生。正如Spring Boot的名稱一樣,一鍵啟動,Spring Boot提供了自動配置功能,為我們提供了開箱即用的功能,使我們將重心放在業務邏輯的開發上。那麼Spring Boot又是怎麼簡化Spring MVC的呢?Spring Boot和Spring、Spring MVC間又是怎樣的關係呢?Spring Boot又有什麼新特點呢?接下來,讓我們走進Spring MVC 到Spring Boot的簡化之路,或許你就能找到這些答案。
Spring vs Spring MVC vs Spring Boot
- Spring Boot和Spring、Spring MVC不是競爭關係,Spring Boot使我們更加容易使用Spring和Spring MVC
Spring FrameWork
- Spring FrameWork解決的核心問題是什麼 Spring框架的最重要特性是依賴注入,所有的Spring模組的核心都是依賴注入(DI)或控制反轉(IOC)。為什麼很重要呢,因為當我們使用DI或IOC時,我們可以使應用得到解耦。我們來看一個簡單的例子:
沒有依賴注入的例子:
@RestController
public class WelcomeController {
private WelcomeService service = new WelcomeService();
@RequestMapping("/welcome")
public String welcome() {
return service.retrieveWelcomeMessage();
}
}
WelcomeService service = new WelcomeService(); 意味著WelcomeController類與WelcomeService類緊密結合在一起,耦合度高。
複製程式碼
使用依賴注入的例子:
@Component
public class WelcomeService {
//Bla Bla Bla
}
@RestController
public class WelcomeController {
@Autowired
private WelcomeService service;
@RequestMapping("/welcome")
public String welcome() {
return service.retrieveWelcomeMessage();
}
}
依賴注入使世界看起來更簡單,我們讓Spring 框架做了辛勤的工作:
@Component:我們告訴Spring框架-嘿,這是一個你需要管理的bean
@Autowired:我們告訴Spring框架-嘿,找到這個特定型別的正確匹配並自動裝入它
複製程式碼
Spring 還能解決什麼問題
1. 重複程式碼
Spring框架停止了依賴注入(DI)嗎?沒有,它在依賴注入(DI)的核心概念上開發了許多Spring模組:
- Spring JDBC
- Spring MVC
- Spring AOP
- Spring ORM
- Spring Test
- ...
考慮一下Spring JDBC,這些模組帶來了新功能嗎?並沒有,我們完全可以使用Java程式碼完成這些工作。那麼,它們給我們帶來了什麼?它們帶來了簡單的抽象,這些簡單抽象的目的是:
- 減少樣板程式碼/減少重複
- 促進解耦/增加單元可測性 例如:與傳統的JDBC相比,我們使用Spring JDBC需要編寫的程式碼減少了許多。
2. 與其他框架良好的整合
Spring框架並不嘗試去解決已經解決了的問題,它所做的一切就是提供與提供出色解決方案的框架的完美整合。
- Hibernate
- IBatis
- JUnit
- ...
Spring MVC
- Spring MVC框架解決的核心問題是什麼 Spring MVC框架提供了開發Web應用的分離方式。通過DispatcherServlet、ModelAndView、View Resolver等簡單概念,是Web應用開發變得更加簡單。
為什麼需要Spring Boot
基於Spring的應用程式有很多配置。當我們使用Spring MVC時,我們需要配置元件掃描,排程器servlet,檢視解析器等:
檢視解析器配置:
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/webjars/**" location="/webjars/"/>
前端排程器的典型配置:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/todo-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
當我們使用Hibernate / JPA時,我們需要配置一個資料來源,一個實體管理器工廠,一個事務管理器以及許多其他事物:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="user" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:config/schema.sql" />
<jdbc:script location="classpath:config/data.sql" />
</jdbc:initialize-database>
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="persistenceUnitName" value="hsql_pu" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
複製程式碼
Spring Boot解決的問題
1. Spring Boot 自動配置
Spring引入了新的思維過程:我們可以變得更加智慧些嗎?當一個spring mvc jar包被新增到應用程式時,我們是否可以自動配置一些bean?
- 當Hibernate jar包在類路徑時,自動配置資料來源怎樣?
- 當Spring MVC jar包在類路徑時,自動配置Dispatcher Servlet怎樣?
- Spring Boot檢視ClASSPATH上對於本應用程式需要編寫配置的框架,基於這些,Spring Boot提供了這些框架的基本配置-這就是自動配置。
2. Spring Boot Starter Projects
假設我們想開發一個Web應用程式。首先,我們需要確定我們想要使用的框架,使用哪個版本的框架以及如何將它們連線在一起。所有Web應用程式都有類似的需求 下面列出的是我們在Spring MVC中使用的一些依賴關係。這些包括Spring MVC,Jackson Databind(用於資料繫結),Hibernate-Validator(用於使用Java驗證API的伺服器端驗證)和Log4j(用於日誌記錄)。在建立時,我們必須選擇所有這些框架的相容版本:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.2.Final</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
複製程式碼
- 什麼是Starter
Starter是一套方便的依賴描述符,可以包含在應用程式中。
你可以獲得所需的所有Spring及相關技術的一站式服務,而無需搜尋示例程式碼並複製依賴描述符的貼上負載。
例如,如果你想開始使用Spring和JPA來訪問資料庫,只需在你的專案中包含spring-boot-starter-data-jpa依賴項就好。
複製程式碼
我們來看Starter的一個示例 - Spring-Boot-Starter-Web
Spring-Boot-Starter-Web依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
複製程式碼
以下螢幕截圖顯示了新增到我們的應用程式中的不同依賴關係:
任何典型的Web應用程式都會使用所有這些依賴項.Spring Boot Starter Web預先打包了這些。作為開發人員,我們不需要擔心這些依賴關係或相容版本。3. Spring Boot Starter專案選項
正如Spring Boot Starter Web一樣,Starter專案幫助我們快速入門開發特定型別的應用程式:
- spring-boot-starter-web-services - SOAP Web服務
- spring-boot-starter-web - Web和RESTful應用程式
- spring-boot-starter-test - 單元測試和整合測試
- spring-boot-starter-data-jpa - 帶有Hibernate的Spring Data JPA
- spring-boot-starter-cache - 啟用Spring Framework的快取支援
- ...
什麼是Spring Boot 自動配置
前面已經初步介紹過,在這裡詳細介紹一下。
當我們啟動Spring Boot應用程式時,我們可以在日誌中看到一些重要的訊息。
Mapping servlet: 'dispatcherServlet' to [/]
Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
複製程式碼
上面的日誌語句顯示了Spring Boot Auto Configuration的行為。
一當我們在應用中新增了Spring Boot Starter Web依賴,Spring Boot AutoConfiguration就會發現Spring MVC在類路徑下,它會自動配置dispatcherServlet,一個預設的錯誤頁面和webjars。
如果你新增了Spring Boot DataJPA Starter依賴,Spring Boot AutoConfiguration會自動配置資料來源(datasource)和實體管理器(Entity Manager)
Spring Boot Auto Configuration在哪裡實現
所有的自動配置邏輯都在spring-boot-autoconfigure.jar中實現。mvc、data和其他框架的所有自動配置邏輯都存在與一個jar包中。
spring-boot-autoconfigure.jar中重要的檔案是/META-INF/spring.factories,該檔案;列出了在EnableAutoConfiguration key下啟動的所有自動配置類。下面列出一些重要的配置類:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
複製程式碼
檢視自動配置
開啟除錯日誌
在application.properties開啟除錯日誌:
logging.level.org.springframework: DEBUG
複製程式碼
當啟動程式時,會列印自動配置日誌資訊
總結
Spring Boot的出現本身就是為了減低Web開發的門檻,使開發人員能夠專注於業務開發,而不需浪費時間在業務開發之外,至此Spring MVC到Spring Boot的簡化之路到此結束。