使用Gradle第一次構建Web應用

Gradle Web 插件

Gradle 提供了打包 war 包的插件,可以將 Web 應用部署到本地 Servlet 容器中。

使用 War 和 Jetty 插件

Gradle 對構建和運行 Web 應用提供了對應擴展的支持。
下面我們介紹 War 和 Jetty 插件。
War 插件擴展自 Java 插件,爲 Web 應用部署和組裝 War 包添加了約定和支持。
Jetty 是一個流行的輕量級開源 Web 容器,Gradle 提供了 Jetty 插件,方便 Jetty 的使用。Jetty 擴展自 War 插件,爲部署一個 Web 應用和運行 Web 應用提供了對應的任務。

War插件

War 插件擴展自 Java 插件,所以我們在引入 War 插件後無需再顯式引入 Java插件(引入也不會影響,應用插件是一個冪等【任意多次執行所產生的影響均與一次執行的影響相同】操作,某一個指定的插件只會運行一次)
使用插件只需:

apply plugin:'war'

對於項目本身,除了 Java 插件的約定外,還會應用 Web 應用文件,並打包項目爲 WAR 文件而不是 JAR 文件。Web 應用默認約定的源代碼目錄是src/main/webapp
添加相關 Web 文件之後我們的文件目錄如下所示:

└─src
    └─main
        ├─java
        │  └─com
        │      └─manning
        │          └─gia
        │              └─todo
        │                  ├─model
        │                  │      ToDoItem.java
        │                  │
        │                  ├─repository
        │                  │      InMemoryToDoRepository.java
        │                  │      ToDoRepository.java
        │                  │
        │                  └─web
        │                          ToDoServlet.java
        │
        └─webapp
            ├─css
            │      base.css
            │      bg.png
            │
            ├─jsp
            │      index.jsp
            │      todo-list.jsp
            │
            └─WEB-INF
                    web.xml

當我們構建的時候會發現報錯:

www.coderknock.com$ gradle build
:compileJava
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:7: 錯誤: 程序包javax.servlet不存在
import javax.servlet.RequestDispatcher;
                    ^
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:8: 錯誤: 程序包javax.servlet不存在
import javax.servlet.ServletException;
                    ^
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:9: 錯誤: 程序包javax.servlet.http不存在
import javax.servlet.http.HttpServlet;
                         ^
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:10: 錯誤: 程序 包javax.servlet.http不存在
import javax.servlet.http.HttpServletRequest;
                         ^
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:11: 錯誤: 程序 包javax.servlet.http不存在
import javax.servlet.http.HttpServletResponse;
                         ^
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:16: 錯誤: 找不 到符號
public class ToDoServlet extends HttpServlet {
                                 ^
  符號: 類 HttpServlet
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:22: 錯誤: 找不 到符號
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                           ^
  符號:   類 HttpServletRequest
  位置: 類 ToDoServlet
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:22: 錯誤: 找不 到符號
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                                                       ^
  符號:   類 HttpServletResponse
  位置: 類 ToDoServlet
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:22: 錯誤: 找不 到符號
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                                                                                            ^
  符號:   類 ServletException
  位置: 類 ToDoServlet
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:29: 錯誤: 找不 到符號
    private String processRequest(String servletPath, HttpServletRequest request) {
                                                      ^
  符號:   類 HttpServletRequest
  位置: 類 ToDoServlet
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:21: 錯誤: 方法 不會覆蓋或迪殖嘈偷姆椒?
      @Override
    ^
D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\src\main\java\com\manning\gia\todo\web\ToDoServlet.java:25: 錯誤: 找不 到符號
        RequestDispatcher dispatcher = request.getRequestDispatcher(view);
        ^
  符號:   類 RequestDispatcher
  位置: 類 ToDoServlet
12 個錯誤
:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 1.21 secs

實現 Web 應用所需要的類並未包括在標準 JDK 中,例如 javax.servlet.HttpServlet。所以在運行構建前我們需要添加外部依賴。我們爲 War 插件引入兩個依賴,Servlet 依賴使用到的是 providedCompile,它表示該依賴在編譯時需要,但實際運行時由運行時的環境提供。在本項目中就是 Jetty 提供,這樣改依賴的相關文件就不會打包到 WAR 文件中了(避免 WAR 包過大以及可能出現的 JAR 包重複從而導致找不到相關類)。向 JSTL 庫等在編譯時不需要,運行時需要的庫,我們需要標記爲 runtime ,這樣他們會被包含到 WAR 文件中以供運行時調用。我們在 build.gradle 中添加下面依賴配置:

dependencies{
     providedCompile 'javax.servlet:javax.servlet-api:3.1.0' //書中是該值,'javax.servlet:servlet-api:2.5' 但是該庫比較舊,我們使用最新的 Servlet 依賴  
     runtime 'javax.servlet:jstl:1.1.2'
 }

這時我們運行構建命令,發現還是有報錯:

www.coderknock.com$ gradle build
> Configuring > 0/1 projects > root project > Compiling D:\Windows\Desktop\LearnGradle\用Gradle做Web開發\build.gradle in:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Could not resolve all dependencies for configuration ':compileClasspath'.
> Cannot resolve external dependency javax.servlet:servlet-api:3.0.1 because no repositories are defined.
  Required by:
      project :

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 1.332 secs

這是因爲我們沒有什麼資源庫,在 build.gradle 中繼續添加:

repositories {
    mavenCentral()
}

繼續編譯,編譯成功

www.coderknock.com$ gradle build
:compileJava
:processResources NO-SOURCE
:classes
:war//由 War 插件提供的任務來打 WAR 包
:assemble
:compileTestJava NO-SOURCE
:processTestResources NO-SOURCE
:testClasses UP-TO-DATE
:test NO-SOURCE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 7.904 secs

War 插件確保了打包的 WAR 文件遵循由 Java EE 規範定義的標準結構。其中主要做的任務如下:
1. 將 Web 應用源代碼目錄 src/main/webapp 的內容拷貝到 WAR 文件的根目錄
2. 將編譯後的 class 文件放入到 WEB-INF/classes 下
3. 通過依賴定義的運行時類庫(如上面的)javax.servlet:jstl:1.1.2 拷貝到 WEB-INF/lib 下

打包後的目錄如下:

│
├─.gradle
│  ├─3.4
│  │  ├─file-changes
│  │  │      last-build.bin
│  │  │
│  │  ├─fileContent
│  │  │      annotation-processors.bin
│  │  │      fileContent.lock
│  │  │
│  │  └─taskHistory
│  │          fileHashes.bin
│  │          fileSnapshots.bin
│  │          jvmClassSignatures.bin
│  │          taskHistory.bin
│  │          taskHistory.lock
│  │
│  └─buildOutputCleanup
│          built.bin
│          cache.properties
│          cache.properties.lock
│
├─build
│  ├─classes
│  │  └─main
│  │      └─com
│  │          └─manning
│  │              └─gia
│  │                  └─todo
│  │                      ├─model
│  │                      │      ToDoItem.class
│  │                      │
│  │                      ├─repository
│  │                      │      InMemoryToDoRepository.class
│  │                      │      ToDoRepository.class
│  │                      │
│  │                      └─web
│  │                              ToDoServlet$ToDoListStats.class
│  │                              ToDoServlet.class
│  │
│  ├─libs
│  │      用Gradle做Web開發.war
│  │
│  └─tmp
│      ├─compileJava
│      └─war
│              MANIFEST.MF
│
│
└─src
    └─main
        ├─java
        │  └─com
        │      └─manning
        │          └─gia
        │              └─todo
        │                  ├─model
        │                  │      ToDoItem.java
        │                  │
        │                  ├─repository
        │                  │      InMemoryToDoRepository.java
        │                  │      ToDoRepository.java
        │                  │
        │                  └─web
        │                          ToDoServlet.java
        │
        └─webapp
            ├─css
            │      base.css
            │      bg.png
            │
            ├─jsp
            │      index.jsp
            │      todo-list.jsp
            │
            └─WEB-INF
                    web.xml

其中打包好的 WAR 文件的目錄結構如下:

├─css
│      base.css
│      bg.png
│
├─jsp
│      index.jsp
│      todo-list.jsp
│
├─META-INF
│      MANIFEST.MF
│
└─WEB-INF
    │  web.xml
    │
    ├─classes
    │  └─com
    │      └─manning
    │          └─gia
    │              └─todo
    │                  ├─model
    │                  │      ToDoItem.class
    │                  │
    │                  ├─repository
    │                  │      InMemoryToDoRepository.class
    │                  │      ToDoRepository.class
    │                  │
    │                  └─web
    │                          ToDoServlet$ToDoListStats.class
    │                          ToDoServlet.class
    │
    └─lib
            jstl-1.2.jar

可以看到其結構正如我們分析的一樣。
相關代碼

發佈了79 篇原創文章 · 獲贊 21 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章