Spring Boot 2.X 來臨,本文將帶你起飛
當前網際網路技術盛行,以Spring 框架為主導的Java 網際網路技術成了主流,而基於Spring 技術衍生出來的Spring Boot,採用了“約定優於配置”的思想,極大地簡化了Spring 框架的開發。
隨著近些年來微服務技術的流行,Spring Boot 也成了時下炙手可熱的熱點技術。2017 年9 月,Spring 框架出現了重大版本升級,從4.x 版本升級為了5.x 版本,隨著這次升級,Spring Boot的版本也在2018年3月從1.x升級到了2.x。
Spring Boot的優點
談到Spring Boot,就讓我們先來了解它的優點。依據官方的文件,Spring Boot的優點如下:
-
建立獨立的Spring應用程式;
-
嵌入的Tomcat、Jetty或者Undertow,無須部署WAR檔案;
-
允許通過Maven來根據需要獲取starter;
-
儘可能地自動配置Spring;
-
提供生產就緒型功能,如指標、健康檢查和外部配置;
-
絕對沒有程式碼生成,對XML沒有要求配置。
這段描述告訴我們,首先Spring Boot是一個基於Spring框架搭建起來的應用,其次它會嵌入Tomcat、Jetty或者Undertow等伺服器,並且不需要傳統的WAR檔案進行部署,也就是說搭建Spring Boot專案並不需要單獨下載Tomcat等傳統的伺服器。
同時提供通過Maven(或者Grandle)依賴的starter,這些starter可以直接獲取開發所需的相關包,通過這些starter專案就能以Java Application的形式執行Spring Boot的專案,而無須其他伺服器配置。
對於配置,Spring Boot提供Spring框架的最大自動化配置,大量使用自動配置,使得開發者對Spring的配置儘量減少。
此外還提供了一些監測、自動檢測的功能和外部配置,與此同時沒有附加程式碼和XML的配置要求。
約定優於配置,這是Spring Boot的主導思想。對於Spring Boot而言,大部分情況下存在預設配置,你甚至可以在沒有任何定義的情況下使用Spring框架,如果需要自定義也只需要在配置檔案配置一些屬性便可以,十分便捷。
而對於部署這些專案必需的功能,Spring Boot提供starter的依賴,例如,spring-boot-starter-web捆綁了Spring MVC所依賴的包,spring-boot-starter-tomcat綁定了內嵌的Tomcat,這樣使得開發者能夠儘可能快地搭建開發環境,快速進行開發和部署,這就是Spring Boot的特色。也許作為傳統開發者的你,還未能理解其意義,但這並不要緊。
為了展示Spring Boot的特色,下節將分別展示傳統Spring MVC專案和簡易的Spring Boot入門例項,並進行比較。
傳統Spring MVC和Spring Boot的對比
在傳統的Spring MVC專案開發中,開發一個簡易的Spring MVC專案,需要配置DispatcherServlet,也需要配置Spring IoC的容器。你可以選擇使用web.xml的配置來實現,當然,如果你使用的是Servlet 3.1規範,也可以繼承由Spring MVC提供的AbstractAnnotationConfigDispatcherServletInitializer來配置Spring MVC專案。
這裡先給出可以執行的程式碼示例,即使你還不熟悉Spring MVC也沒有關係,這裡只是為了說明開發比較煩瑣而已,後面將詳談Spring MVC的開發原理。
假設你已經匯入需要的Spring和Spring MVC相關的依賴包到工程中,那麼就可以開始配置DispatcherServlet了。例如,程式碼清單1-1就是通過繼承AbstractAnnotationConfigDispatcherServletInitializer的方式來配置Spring MVC的DispatcherServlet的。
程式碼清單1-1 配置Spring MVC
package com.springboot.springmvc.conf;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// Spring IoC容器配置
@Override
protected Class<?>[] getRootConfigClasses() {
// 可以返回Spring的Java配置檔案陣列
return new Class<?>[] {};
}
// DispatcherServlet的URI對映關係配置
@Override
protected Class<?>[] getServletConfigClasses() {
// 可以返回Spring的Java配置檔案陣列
return new Class<?>[] { WebConfig.class };
}
// DispatcherServlet攔截請求匹配
@Override
protected String[] getServletMappings() {
return new String[] { "*.do" };
}
}
注意程式碼中加粗的地方。這裡引入了一個Java配置檔案—— WebConfig.java,它的主要作用是配置Spring MVC的核心類DispatcherServlet的上下文,如程式碼清單1-2所示。
程式碼清單1-2 配置DispatcherServlet的上下文
package com.springboot.springmvc.conf;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
// 定義Spring MVC掃描的包
@ComponentScan(value="com.*",
includeFilters = {@Filter(type = FilterType.ANNOTATION,
value = Controller.class)})
// 啟動Spring MVC配置
@EnableWebMvc
public class WebConfig {
/***
* 通過註解@Bean初始化檢視解析器
*
* @return ViewResolver檢視解析器
*/
@Bean(name = "internalResourceViewResolver")
public ViewResolver initViewResolver() {
InternalResourceViewResolver viewResolver
= new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
/**
* 初始化RequestMappingHandlerAdapter,並載入HTTP的JSON轉換器
*
* @return RequestMappingHandlerAdapter 物件
*/
@Bean(name = "requestMappingHandlerAdapter")
public HandlerAdapter initRequestMappingHandlerAdapter() {
// 建立RequestMappingHandlerAdapter介面卡
RequestMappingHandlerAdapter rmhd = new RequestMappingHandlerAdapter();
// HTTP JSON轉換器
MappingJackson2HttpMessageConverter jsonConverter
= new MappingJackson2HttpMessageConverter();
// MappingJackson2HttpMessageConverter接收JSON型別訊息的轉換
mediaType = MediaType.APPLICATION_JSON_UTF8;
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(mediaType);
// 加入轉換器的支援型別
jsonConverter.setSupportedMediaTypes(mediaTypes);
// 給介面卡加入JSON轉換器
rmhd.getMessageConverters().add(jsonConverter);
return rmhd;
}
}
通過上面的程式碼,配置完成Spring MVC的開發環境後,才可以開發Spring MVC控制器Controller,這樣就可以開發一個簡單的控制器(Controller),如程式碼清單1-3所示。
程式碼清單1-3 開發Spring MVC控制器
package com.springboot.springmvc.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public Map<String, String> test() {
Map<String, String> map = new HashMap<String, String>();
map.put("key", "value");
return map;
}
}
這樣就完成了一個傳統Spring MVC的開發,但是你還需要第三方伺服器,如Tomcat、WebLogic等伺服器去部署你的工程。在啟動伺服器後,再開啟瀏覽器,輸入對應的URL,如專案名稱為SpringMVC則輸入http://localhost:8080/SpringMVC/test.do,就可以得到圖1-1所示的頁面。
圖1-1 測試傳統的Spring MVC專案
從上面來看,傳統的Spring MVC開發需要配置的內容還是比較多的,而且對設計人員要求較高。開發完成後,開發者還需要找到對應的伺服器去執行,如Tomcat或者Jetty等,這樣既要進行開發,又要進行配置和部署,工作量還是不少的。
而使用Spring Boot開發後,你就會發現原來一切可以那麼簡單。不過在入門階段暫時不需要討論太多的細節問題,這是未來需要討論的問題,所以這裡只展示它是如何簡單而已。首先我們在IDE中建立一個Maven工程,並把其名稱定義為Chapter1,這樣就可以看到一個Maven配置檔案pom.xml,將其內容修改為如程式碼清單1-4所示。
程式碼清單1-4 配置Spring Boot依賴環境
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>springboot</groupId>
<artifactId>chapter1</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>chapter1 Maven Webapp</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</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>
<!-- Spring Boot Starter依賴引入 -->
<!-- AOP包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Web開發包,將載入Spring MVC所需要的包,且內嵌tomcat -->
<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>
從加粗的程式碼中可以看到Maven的配置檔案引入了多個Spring Boot的starter,Spring Boot會根據Maven配置的starter去尋找對應的依賴,將對應的jar包載入到工程中,而且它還會把繫結的伺服器也載入到工程中,這些都不需要你再進行處理。
正如Spring Boot承諾的那樣,繫結伺服器,並且實現Spring的儘可能的配置,採用約定優於配置的原則。這裡我們只需要開發一個類就可以執行Spring Boot的應用了,為此新建類——Chapter1Main,如程式碼清單1-5所示。
程式碼清單1-5 開發Spring Boot應用
package com.springboot.chapter1;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
// 啟用Spring Boot自動裝配
@EnableAutoConfiguration
public class Chapter1Main {
@RequestMapping("/test")
@ResponseBody
public Map<String, String> test() {
Map<String, String> map = new HashMap<String, String>();
map.put("key", "value");
return map;
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Chapter1Main.class, args);
}
}
好了,這個入門例項已經完結了。如果你沒有接觸過Spring Boot那麼你會十分驚訝,這樣就配置完成Spring MVC的內容了嗎?我可以回答你:“是的,已經完成了,現在完全可以使用Java Application的形式去執行類Chapter1Main。”下面是Spring Boot的執行日誌:
1 . ____ _ __ _ _ 2 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ 3( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ' |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v2.0.0.RELEASE) 8 92018-03-01 22:21:55.843 INFO 16324 --- [ main] 10com.springboot.chapter1.Chapter1Main : 11Starting Chapter1Main on AFOIF-703271542 with PID 16324 12(G:\springboot\v2\chapter1\target\classes started by Administrator in 13G:\springboot\v2\chapter1) 14...... 152018-03-01 22:21:57.270 INFO 16324 --- [ main] 16s.w.s.m.m.a.RequestMappingHandlerMapping : 17Mapped "{[/test]}" onto public java.util.Map<java.lang.String, java.lang.String> 18com.springboot.chapter1.Chapter1Main.test() 19...... 202018-03-01 22:21:57.270 INFO 16324 --- [ main] 21com.springboot.chapter1.Chapter1Main : Started Chapter1Main in 1.845 seconds (JVM running for 2.143) 22
從日誌中可以看到,Tomcat已經啟動,並且將我們開發的Chapter1Main作為Spring MVC的控制器載入進來了,也將對應的路徑(/test)對映到開發的test方法上。因此,接下來就可以進行測試了。開啟瀏覽器,在位址列輸入http://localhost:8080/test,可以看到如圖1-2所示的結果。
圖1-2Spring Boot執行結果
與傳統的Spring MVC是不是很不一樣呢?從上面的對比可以看出,Spring Boot 允許直接進行開發,這就是它的優勢。在傳統所需要配置的地方,Spring Boot都進行了約定,也就是你可以直接以Spring Boot約定的方式進行開發和執行你的專案。
當你需要修改配置的時候,它也提供了一些快速配置的約定,猶如它所承諾的那樣,儘可能地配置好Spring專案和繫結對應的伺服器,使得開發人員的配置更少,更加直接地開發專案。
對於那些微服務而言,更喜歡的就是這樣能夠快速搭建環境的專案,而Spring Boot提供了這種可能性,同時Spring Boot還提供了監控的功能。
隨著雲技術的到來,微服務成了市場的熱點,於是代表Java微服務時代的Spring Boot微服務開發的時代已經到來,結合Spring Cloud後它還能很方便地構建分散式系統開發,滿足大部分無能力單獨開發分散式架構的企業所需,所以這無疑是激動人心的技術。