首先到GitHub
上clone
下Spring Boot
的代碼:html
git clone https://github.com/spring-projects/spring-boot.git
因爲Spring Boot
的發佈版本代碼都在tag
上,因此須要使用git tag
命令查看全部的tag
:java
git tag
而後切換到名爲v2.0.0.RELEASE
的tag
上:git
git checkout -b v2.0.0.RELEASE v2.0.0.RELEASE
這樣,代碼就被保存到本地分支v2.0.0.RELEASE
上了。github
Spring Boot
官方建議使用./mvnw clean install
或者標準的mvn clean install
命令來編譯源代碼,若是要使用標準的mvn
命令的話,Maven
的版本要求在3.5.0
或以上。導入IDEA
源碼視圖以下:web
接着切換到spring-boot
根目錄下,執行以下命令,我這裏使用的Maven
版本是3.5.4:spring
mvn -Dmaven.test.skip=true clean install
以上命令對Spring Boot
源碼打包並安裝到本地maven
倉庫,在打包過程當中會忽略測試,由於運行單元測試時間特別長,下載源碼的目的是學習和分析Spring Boot
的原理,而並非作定製開發,所以一些不影響學習的單元測試能夠忽略掉,能夠不關注單測的結果。命令執行結果以下:apache
打包失敗主要是由於失敗單元測試引發的,這些單元測試會影響最終編譯打包結果:json
org.springframework.boot.gradle.plugin.OnlyDependencyManagementIntegrationTests > dependencyManagementCanBeConfiguredUsingCoordinatesConstant [Gradle default] FAILED java.lang.RuntimeException at OnlyDependencyManagementIntegrationTests.java:42 Caused by: org.gradle.testkit.runner.UnexpectedBuildFailure at OnlyDependencyManagementIntegrationTests.java:42 org.springframework.boot.gradle.plugin.OnlyDependencyManagementIntegrationTests > dependencyManagementCanBeConfiguredUsingCoordinatesConstant [Gradle 4.1] FAILED java.lang.RuntimeException at OnlyDependencyManagementIntegrationTests.java:42 Caused by: org.gradle.testkit.runner.UnexpectedBuildFailure at OnlyDependencyManagementIntegrationTests.java:42 org.springframework.boot.gradle.plugin.OnlyDependencyManagementIntegrationTests > dependencyManagementCanBeConfiguredUsingCoordinatesConstant [Gradle 4.2] FAILED java.lang.RuntimeException at OnlyDependencyManagementIntegrationTests.java:42 Caused by: org.gradle.testkit.runner.UnexpectedBuildFailure at OnlyDependencyManagementIntegrationTests.java:42 org.springframework.boot.gradle.plugin.OnlyDependencyManagementIntegrationTests > dependencyManagementCanBeConfiguredUsingCoordinatesConstant [Gradle 4.3] FAILED java.lang.RuntimeException at OnlyDependencyManagementIntegrationTests.java:42 Caused by: org.gradle.testkit.runner.UnexpectedBuildFailure at OnlyDependencyManagementIntegrationTests.java:42 org.springframework.boot.gradle.plugin.OnlyDependencyManagementIntegrationTests > dependencyManagementCanBeConfiguredUsingCoordinatesConstant [Gradle 4.4.1] FAILED java.lang.RuntimeException at OnlyDependencyManagementIntegrationTests.java:42 Caused by: org.gradle.testkit.runner.UnexpectedBuildFailure at OnlyDependencyManagementIntegrationTests.java:42 org.springframework.boot.gradle.plugin.OnlyDependencyManagementIntegrationTests > dependencyManagementCanBeConfiguredUsingCoordinatesConstant [Gradle 4.5] FAILED java.lang.RuntimeException at OnlyDependencyManagementIntegrationTests.java:42 Caused by: org.gradle.testkit.runner.UnexpectedBuildFailure at OnlyDependencyManagementIntegrationTests.java:42
這些失敗的單測屬於spring-boot-project/spring-boot-tools
下的spring-boot-gradle-plugin
項目,一個比較暴力的解決辦法是直接刪掉這個項目下的src/test/java
,不運行這個項目的單測,由於暫時也用不到它。刪除後再執行:瀏覽器
mvn -Dmaven.test.failure.ignore=true -Dmaven.test.skip=true clean install
以上命令中的-Dmaven.test.failure.ignore=true
會使Maven
忽略掉失敗的單元測試,等待命令執行5-10分鐘,顯示執行成功:tomcat
接下來就能夠建立測試項目進行源碼調試了。
打包成功以後,在spring-boot/spring-boot-project
目錄下建立一個Spring Boot
項目測試一下本身編譯的源碼是否能夠正常運行,在spring-boot-project
上點擊New->Module
爲它建立一個名爲spring-boot-example
的子module
,接着按照標準Spring Boot
服務的順序來建立Application
、配置文件application.yml
和相應的controller
,建立完成後,視圖以下:
代碼依次以下:
一、Application類:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
二、WebController類:
@Controller @RequestMapping(value = "/web", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public class WebController { @GetMapping(value = "/test") public List test() { List list = new ArrayList(); list.add("這是測試"); return list; } }
三、application.yml:
server: port: 6011 spring: application: name: spring-boot-example
四、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"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-parent</artifactId> <version>${revision}</version> <relativePath>../spring-boot-parent</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-boot-example</artifactId> <packaging>jar</packaging> <name>spring-boot-example Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <!-- Compile --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>spring-boot-example</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> <!-- Add --> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <useSystemClassLoader>false</useSystemClassLoader> </configuration> </plugin> </plugins> </build> </project>
接下來,還須要將spring-boot-project/spring-boot-parent
和spring-boot-project/spring-boot-starters
兩個項目的pom.xml
裏的maven-checkstyle-plugin
信息註釋掉,才能夠運行的測試項目,由於這個插件會對代碼進行檢查,檢查失敗的話,服務運行不起來。
最後,直接運行Application
類,輸出運行成功日誌:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: 2018-09-04 11:07:37.046 INFO 4576 --- [ main] o.s.boot.example.Application : Starting Application on Armons-MacBook-Pro.local with PID 4576 (/Users/pengwang/Documents/workspace-oxygen/data/spring-boot/spring-boot-project/spring-boot-example/target/classes started by wangpeng in /Users/pengwang/Documents/workspace-oxygen/data/spring-boot) 2018-09-04 11:07:37.079 INFO 4576 --- [ main] o.s.boot.example.Application : No active profile set, falling back to default profiles: default 2018-09-04 11:07:37.248 INFO 4576 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@75c072cb: startup date [Tue Sep 04 11:07:37 CST 2018]; root of context hierarchy 2018-09-04 11:07:40.565 INFO 4576 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 6011 (http) 2018-09-04 11:07:40.619 INFO 4576 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-09-04 11:07:40.619 INFO 4576 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.28 2018-09-04 11:07:40.641 INFO 4576 --- [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/pengwang/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.] 2018-09-04 11:07:40.837 INFO 4576 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-09-04 11:07:40.838 INFO 4576 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3594 ms 2018-09-04 11:07:41.179 INFO 4576 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/] 2018-09-04 11:07:41.183 INFO 4576 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2018-09-04 11:07:41.184 INFO 4576 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2018-09-04 11:07:41.184 INFO 4576 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] 2018-09-04 11:07:41.184 INFO 4576 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] 2018-09-04 11:07:41.617 INFO 4576 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@75c072cb: startup date [Tue Sep 04 11:07:37 CST 2018]; root of context hierarchy 2018-09-04 11:07:41.731 INFO 4576 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/web/test],methods=[GET],produces=[application/json;charset=UTF-8]}" onto public java.util.List org.springframework.boot.example.WebController.test() 2018-09-04 11:07:41.738 INFO 4576 --- [ 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-09-04 11:07:41.739 INFO 4576 --- [ 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-09-04 11:07:41.791 INFO 4576 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-09-04 11:07:41.792 INFO 4576 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-09-04 11:07:41.849 INFO 4576 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-09-04 11:07:42.101 INFO 4576 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2018-09-04 11:07:42.175 INFO 4576 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 6011 (http) with context path '' 2018-09-04 11:07:42.180 INFO 4576 --- [ main] o.s.boot.example.Application : Started Application in 6.077 seconds (JVM running for 6.955)
打開瀏覽器訪問http://localhost:6011/web/test,頁面顯示:
[ "這是測試" ]
至此,源碼編譯打包運行完畢。
開源框架之因此被不少人使用,一方面是由於解決了一些常見的痛點問題,一方面是由於可靠和健壯,保證用開源框架開發出來的服務高可用。提升服務可靠和健壯的一方面就是單元測試,單元測試雖然繁瑣,但讓咱們對本身寫的代碼和別人寫的代碼可靠性瞭然於胸。