<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      用Gradle構建Spring Boot項目

      相比起Maven的XML配置方式,Gradle提供了一套簡明的DSL用于構建Java項目,使我們就像編寫程序一樣編寫項目構建腳本。本文將從無到有創(chuàng)建一個用Gradle構建的Spring Boot項目,并在此過程中講到Gradle的一些典型用法。

      本文Github代碼:https://github.com/davenkin/gradle-spring-boot.git


      創(chuàng)建Gradle工程

      Gradle采用了與Maven相同的目錄組織結構,你可以通過Spring Initializr網(wǎng)站創(chuàng)建Spring Boot工程。但是在本文中,我們將全部通過命令行操作創(chuàng)建Spring Boot工程。首先在命令行中創(chuàng)建如下目錄結構:

      └── src
          ├── main
          │   └── java
          └── test
              └── java
      

      然后在src同級目錄中添加一個build.gradle文件,內(nèi)容如下:

      apply plugin: 'java'
      

      大功告成,一個用Gradle構建的Java項目創(chuàng)建好了,盡情用以下命令編譯并打包咱們的Java項目吧:

      gradle build
      

      只是現(xiàn)在咱們的Java項目還是一個空架子,不用急,在下文中我們將一步一步在這個空架子中搭建一個有血有肉的Spring Boot項目。

      值得一提的是,雖然此時的build.gradle文件中只有一行配置(apply plugin: 'java',作用是引入java插件),但是其背后已經(jīng)幫我們做了很多事情,比如它使得我們能夠運行gradle build命令。這里的build即為Gradle中的一個任務(Task),我們還可以運行以下命令查看到更多的Task。

      gradle tasks
      

      此時輸出:

      ...
      Build tasks
      -----------
      assemble - Assembles the outputs of this project.
      build - Assembles and tests this project.
      buildDependents - Assembles and tests this project and all projects that depend on it.
      buildNeeded - Assembles and tests this project and all projects it depends on.
      classes - Assembles main classes.
      clean - Deletes the build directory.
      jar - Assembles a jar archive containing the main classes.
      testClasses - Assembles test classes.
      ...
      

      這里的assemble、build和jar等Task都是java插件引入的。build.gradle是Gradle的配置文件,更多關于Gradle的知識請參考筆者的Gradle學習系列文章


      使用Gradle Wrapper

      對于所有的Gradle項目來說,筆者都推薦使用Gradle Wrapper,甚至應該將其當做創(chuàng)建代碼庫之后的第一件事來做。使用Gradle Wrapper有以下好處:

      1. 不用安裝gradle也能運行gradle
      2. 所有人使用相同的gradle版本

      在build.gradle中加入以下配置:

      task wrapper(type: Wrapper) {
          gradleVersion = '3.0'
      }
      

      然后在命令行運行:

      gradle wrapper
      

      此時會生成以下三個文件(夾):gradlew、gradlew.bat和gradle目錄。

      這里的gradlew和gradlew.bat其實只是腳本文件(前者用于Unix/Linux/Mac,后者用于Windows),在使用gradle命令的地方替換為gradlew或gradlew.bat,他們將自動下載指定的gradle版本,然后用該版本進行項目構建。如上文所示,本文中我們配置gradle版本為3.0。

      請注意,這三個文件(夾)都需要提交到代碼庫中。當項目其他人拿到代碼之后,由于gradlew和gradlew.bat文件均在源代碼中,他們本地即便沒有gradle,依然可以通過以下命令進行項目構建:

      ./gradlew build
      

      如果你的項目有持續(xù)集成(CI)服務器(你也應該有),那么你的CI機器也沒有必要安裝Gradle了。另外,此時所有人都是使用的相同版本的gradle,進而避免了由于版本不同所帶來的問題。


      添加Spring Boot依賴

      在本文中,我們的業(yè)務非常簡單———輸出“Hello World!”。但是麻雀雖小,五臟俱全,首先需要在build.gradle中配置spring-boot插件,并引入Spring的Web組件,整個build.gradle如下:

      buildscript {
          repositories {
              jcenter()
          }
          dependencies {
              classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE")
          }
      }
      
      repositories {
          jcenter()
      }
      
      apply plugin: 'java'
      apply plugin: 'org.springframework.boot'
      
      
      sourceCompatibility = 1.8
      targetCompatibility = 1.8
      
      
      task wrapper(type: Wrapper) {
          gradleVersion = '3.0'
      }
      
      dependencies {
          compile("org.springframework.boot:spring-boot-starter-web")
          testCompile("org.springframework.boot:spring-boot-starter-test")
      }
      
      

      然后創(chuàng)建Application類:

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

      依然很簡單,是吧?!這個Application類便是Spring Boot程序的入口。另外我們還需要一個Controller和一個業(yè)務類HelloWorld:

      HelloWorldController:

      @RestController("/helloworld")
      public class HelloController {
      
          private HelloWorld helloWorld;
      
          public HelloController(HelloWorld helloWorld) {
              this.helloWorld = helloWorld;
          }
      
          @GetMapping
          public String hello() {
              return helloWorld.hello();
          }
      }
      

      HelloWorld:

      @Component
      public class HelloWorld {
      
          public String hello() {
              return "Hello World!";
          }
      }
      

      此時工程的目錄結構為:

      ├── README.md
      ├── build.gradle
      ├── gradle
      │   └── wrapper
      │       ├── gradle-wrapper.jar
      │       └── gradle-wrapper.properties
      ├── gradlew
      ├── gradlew.bat
      └── src
          ├── main
          │   └── java
          │       └── davenkin
          │           ├── Application.java
          │           ├── HelloController.java
          │           └── HelloWorld.java
          └── test
              └── java
      

      然后運行:

      ./gradlew bootRun
      

      在瀏覽器或者Postman中打開http://localhost:8080/gradle-spring-boot/helloworld,便可以看到久違的"Hello World!"了。


      生成IDE工程文件

      我曾經(jīng)看到不少人在Eclipse或者IntelliJ IDEA中導入Maven/Gradle工程,甚至在IDE中使用嵌入Tomcat容器。我并不推薦這么做,這些嚴重依賴于GUI操作的功能其實是很笨拙、很脆弱的。以嵌入Tomcat容器為例,它要求項目中所有人都在自己的IDE中手動地對Tomcat進行配置,而手動的過程總是容易出錯的。在持續(xù)交付中有個原則是“凡是能夠自動化的,都應該自動化”,這里的自動化說白了其實就是代碼化。

      因此,在使用Gradle時,筆者更推崇的一種方式是通過Gradle的IDE插件一鍵式地生成IDE工程文件,然后在IDE中直接打開這樣的工程文件。這樣的好處一是非常簡單,二是所有人都使用了相同的IDE配置。

      在Gradle中配置IntelliJ IDEA插件,只需在build.gradle中配置:

          apply plugin: 'idea'
      

      然后運行:

      ./gradlew idea
      

      此時將生成后綴為ipr的IntelliJ IDEA工程文件,在IntelliJ IDEA中直接打開(Open)該文件即可。

      對于Eclipse,在build.gradle中增加以下配置:

          apply plugin: 'eclipse'
      

      然后運行:

      ./gradlew eclipse
      

      此時將生成Eclipse的.project工程文件。

      請注意,所有IDE工程文件都不應該提交到代碼庫,對于Git來說應該將這些文件注冊到.gitignore文件中。各個開發(fā)者拿到代碼后需要各自運行./graldlw idea或./gradlew eclipse命令以生成本地工程文件。


      調(diào)試

      至少有兩種方式可以對Spring Boot項目進行調(diào)試。一種是直接運行命令:

      ./gradlew bootRun --debug-jvm
      

      此時程序將默認監(jiān)聽5005端口,并暫停以等待調(diào)試客戶端的連接,然后啟動Spring Boot。

      另一種方式是使用Gradle的Application插件,在build.gradle中添加:

      apply plugin: 'application'
      applicationDefaultJvmArgs = [ "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" ]
      

      此時運行:

      ./gradlew bootRun
      

      程序將啟動并監(jiān)聽5005調(diào)試端口,但是與第一種方法不同的是,程序不會暫停,而是將直接啟動整個Spring Boot程序。如果你想調(diào)試Spring Boot在啟動過程中的某些代碼,比如Spring框架啟動代碼,那么請選擇第一種方式;否則,第二種是更合適的選擇,因為我們并不是每次啟動程序都一定會調(diào)試的,對吧?!


      自動化測試

      軟件項目可以包含多種自動化測試,比如單元測試、集成測試、功能測試等。對于Spring Boot項目來說,筆者推薦將自動化測試劃分為單元測試和API測試,其中單元測試即是傳統(tǒng)的單元測試,而API測試包含了集成測試、功能測試和端到端測試的功能,它的測試對象是程序向外暴露的REST API接口,在測試時我們需要啟動整個Spring Boot程序,然后模擬客戶端調(diào)用這些API接口來完成業(yè)務測試用例。

      單元測試相對比較簡單,Spring Boot也提供了一些有助于單元測試的設施,但是我并不推薦大家使用,因為單元測試應該是非常純粹、粒度非常小的測試,不應該有框架摻和。

      通常來說,單元測試和API測試應該是分離的,也即他們的代碼應該是分開的,運行測試的命令也應該是不同的。但是這給Gradle帶來了難題,因為默認情況下Gradle只提供一個./gradlew test命令用于測試,并且默認要求測試代碼位于src/test/java目錄下。為此,我們需要對Gradle進行改造。

      我們的目的是:

      • 默認的src/test/java目錄用于單元測試代碼,通過./gradlew test運行
      • 新建src/apiTest/java目錄用于API測試代碼,通過./gradlew apiTest運行

      可以看到,我么將Gradle默認的測試設施用于了單元測試,也即對于單元測試我們不需要做任何改變。對于API測試而言,首先我們需要添加名為apiTest的源代碼集合(SrouceSet),該SourceSet即對應了src/apiTest/java目錄,在build.gradle文件中增加如下配置:

      sourceSets {
          apiTest {
              compileClasspath += main.output + test.output
              runtimeClasspath += main.output + test.output
          }
      }
      
      configurations {
          apiTestCompile.extendsFrom testCompile
          apiTestRuntime.extendsFrom testRuntime
      }
      
      
      

      然后,添加一個Test類型的Task用于運行src/apiTest/java目錄下的API測試代碼:

      task apiTest(type: Test) {
          testClassesDir = sourceSets.apiTest.output.classesDir
          classpath = sourceSets.apiTest.runtimeClasspath
      }
      

      為了使Intelli IDEA能夠感知到這些新添加的測試代碼,我們需要對Gradle的idea插件進行額外配置:

      idea {
          module {
              testSourceDirs += file('src/apiTest/java')
              testSourceDirs += file('src/apiTest/resources')
              scopes.TEST.plus += [configurations.apiTestCompile]
              scopes.TEST.plus += [configurations.apiTestRuntime]
          }
      }
      

      另外,為了使本地構建(./gradlew biuld)過程能夠先運行單元測試,再運行API測試,我們還需要做以下配置:

      apiTest.mustRunAfter test
      build.dependsOn apiTest
      

      第一行的意思是API測試必須運行在單元測試之后,第二行的意思是將API測試包含在build任務中。


      使用JaCoCo

      JaCoCo是一款代碼測試覆蓋率統(tǒng)計工具,我們主要將其用于統(tǒng)計單元測試的覆蓋率。在build.gradle中增加配置:

      apply plugin: "jacoco"
      

      此時運行./gradlew build之后,JaCoCo將在build/jacoco目錄下為單元測試和API測試分別生成原始數(shù)據(jù)文件(test.exec和apiTest.exec),但是此時并沒有測試報告生成,為此,我們還需要單獨運行:

      ./gradlew jacocoTestReport
      

      在瀏覽器中打開build/report/jacoco/test/index.html,你將看到單元測試覆蓋率報告:

      單元測試覆蓋率報告

      但是,此時的覆蓋率報告只是針對單元測試的,為了得到API測試的覆蓋率,我們需要添加一個新的Task:

      task jacocoApiTestReport(type: JacocoReport){
          sourceSets sourceSets.main
          executionData apiTest
      }
      

      然后運行:

      ./gradlew jacocoApiTestReport
      

      在瀏覽器中打開build/report/jacoco/jacocoApiTestReport/index.html,你將看到單元測試覆蓋率報告。

      有時,我們希望看到單元測試和API測試的整體覆蓋率,此時我們需要再添加一個Task:

      //Unit Test and API Test Code coverage all together
      task jacocoAllTestReport(type: JacocoReport){
          sourceSets sourceSets.main
          executionData test, apiTest
      }
      

      然后運行:

      ./gradlew jacocoAllTestReport
      

      在瀏覽器中打開build/report/jacoco/jacocoAllTestReport/index.html,你將看到所有測試整合后的覆蓋率報告。

      作為演示,我們在HelloWorld中添加一個新的anotherHello()方法,此時HelloWorld為:

      @Component
      public class HelloWorld {
      
          public String hello() {
              return "Hello World!";
          }
      
          public String anotherHello() {
              return "Another Hello World!";
          }
      }
      
      

      對應的HelloWorldController也變?yōu)椋?/p>

      @RestController
      public class HelloController {
      
          private HelloWorld helloWorld;
      
          public HelloController(HelloWorld helloWorld) {
              this.helloWorld = helloWorld;
          }
      
          @GetMapping("/helloworld")
          public String hello() {
              return helloWorld.hello();
          }
      
      
          @GetMapping("/anotherHelloworld")
          public String anotherHello() {
              return helloWorld.anotherHello();
          }
      }
      

      然后,我們讓HelloWorld的單元測試只測試hello()方法,讓API測試只測試anotherHello()方法(也即只調(diào)用“anotherHelloworld”的URL接口)。

      此時單元測試覆蓋率為:

      單元測試覆蓋率

      可以看到,anohterHello()方法沒有被單元測試覆蓋到。而集成測試雖然覆蓋到了anotherHello()方法,卻沒有覆蓋到hello()方法:

      API測試覆蓋率

      總體測試覆蓋率為:

      總體測試覆蓋率

      此時,總體測試覆蓋率同時統(tǒng)計了單元測試和集成測試的覆蓋率。


      使用Checkstyle

      CheckStyle是一種靜態(tài)代碼檢查工具,主要用于檢查代碼風格或格式是否滿足要求。首先,我們需要一份配置文件來配置這樣的要求,這里我們采用Google的Checkstyle配置文件。

      在biuld.gradle中增加checkstyle插件:

      apply plugin: 'checkstyle'
      

      下載Google的checkstyle文件并將其拷貝為config/checkstyle/checkstyle.xml,Gradle的checkstyle插件默認將讀取該配置文件。CheckStyle檢查將包含在./gradlew build中。注:在筆者電腦上,使用Google原始Checkstyle配置文件總是報錯,對Checkstyle進行了一些精簡之后運行成功。


      總結

      在本文中,我們從無到有創(chuàng)建了一個使用Gradle構建的Spring Boot項目,包括了對項目的編譯打包、運行單元測試和API測試,并且獲得測試覆蓋率報告。另外,我們提倡使用Gradle的idea/eclipse插件生成IDE工程文件,最后我們使用Checkstyle插件對代碼風格/格式做了靜態(tài)檢查。

      posted @ 2017-04-07 22:22  無知者云  閱讀(55994)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 国产精品黄色片在线观看| 国产激情无码一区二区三区| 99福利一区二区视频| 这里只有精品免费视频 | 亚洲欧洲色图片网站| 激情综合五月网| 国产老熟女乱子一区二区| 国内精品久久黄色三级乱| 116美女极品a级毛片| 国产自在自线午夜精品| 给我免费观看片在线| 国产精品中文字幕av| 日本一区二区中文字幕久久| 国产永久免费高清在线观看| 柠檬福利第一导航在线| 亚洲天堂一区二区成人在线| 人妻少妇偷人精品免费看| 国产高清一区二区不卡| 亚洲精品麻豆一二三区| 任我爽精品视频在线播放| 国产精品普通话国语对白露脸| 国产精品国产精品国产专区不卡| 国产一区二区三区18禁| japan黑人极大黑炮| 精品少妇人妻av无码久久| 一区二区免费高清观看国产丝瓜| 亚州av第二区国产精品| 久久精品波多野结衣| 图片区 小说区 区 亚洲五月| 四虎国产精品久久免费地址| 国产91小视频在线观看| 成人午夜电影福利免费| 国产精品成人一区二区不卡| 国产精品一区二区三区激情| 国产办公室秘书无码精品99| 女高中生自慰污污网站| 国产精品亚洲一区二区三区| 成人国产精品一区二区网站公司| 爽爽精品dvd蜜桃成熟时电影院| 亚洲精品久久久久久无码色欲四季| 国产精品一区二区三区性色|