使用 Android Studio 開(kāi)發(fā) Web 程序 - 調(diào)試

調(diào)試

這是 “使用 Android Studio 開(kāi)發(fā) Web 程序” 系列的第三篇文章植锉,接續(xù)前一篇文章的內(nèi)容页衙,源代碼照著規(guī)格打完了区转,第一件事當(dāng)然就是先運(yùn)行看看成果,如果有出現(xiàn)不符預(yù)期的結(jié)果瞻润,就要進(jìn)到了調(diào)試的程序以便修正源代碼喘垂。但如果負(fù)責(zé)的是 Server 端的元件,還要先準(zhǔn)備好 Container 的環(huán)境绍撞、布署編譯好的檔案正勒、調(diào)整設(shè)定檔等等的程序。過(guò)往大部份人可能都會(huì)選擇 Tomcat 做為 Container傻铣,而現(xiàn)在有一個(gè)輕量化的選擇 Jetty章贞。

Jetty 已在 Gradle 的支持范圍內(nèi),透過(guò) Gradle 的 Jetty Plugin 來(lái)運(yùn)行 jettyRun Task 就可以直接啟動(dòng) Jetty矾柜,并透過(guò)瀏覽器來(lái)檢視程序運(yùn)行后的網(wǎng)頁(yè)結(jié)果阱驾,不需要再加外進(jìn)行安裝 Jetty 的動(dòng)作。

使用 Jetty Plugin 的 build.gradle 檔案內(nèi)容怪蔑,示范如下:

apply plugin: "war"
apply plugin: "jetty"

dependencies {
   compile "javax.servlet:servlet-api:2.5"
}

httpPort = 8080
stopPort = 9090
stopKey = "stopKey"

以下是使用 Android Studio 的 Terminal 窗口下指令后顯示的結(jié)果(運(yùn)行前要先切換到項(xiàng)目所在的文件夾):

如果運(yùn)行成功里覆,就可以依照結(jié)果上出現(xiàn)的網(wǎng)址輸入在瀏覽器里,瀏覽器會(huì)顯示程序運(yùn)行的結(jié)果缆瓣。另外喧枷,由于 Android Studio 產(chǎn)生的 Gradle 項(xiàng)目預(yù)設(shè)會(huì)使用 Gradle Wrapper,Wrapper 會(huì)被產(chǎn)生在項(xiàng)目的相同文件夾下弓坞。運(yùn)行時(shí)是使用名稱為 gradlew 的 Wrapper隧甚,在 Windows 的平臺(tái)是批文件、非 Windows 的平臺(tái)則為 Shell Script渡冻,<u>Shell Script 要先設(shè)定運(yùn)行的權(quán)限</u>戚扳。透過(guò) Wrapper 會(huì)自動(dòng)下載 Gradle 的程序后運(yùn)行,所以不用先行安裝 Gradle族吻,但是如果對(duì) Gradle 版本有特別要求的話帽借,則要改為使用自行安裝 Gradle 的方式珠增。

只是要在 IDE 中設(shè)斷點(diǎn),并且在瀏覽器提出要求的過(guò)程中觸發(fā)中斷砍艾,還需要在命令列中增加以下的參數(shù):

—Dorg.gradle.daemon=true -Dorg.gradle.jvmargs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"

第一個(gè)參數(shù)是要 Gradle 以 Daemon 模式運(yùn)作蒂教,Daemon 模式下會(huì)重用 Process、減少 Gradle 程序啟動(dòng)的成本脆荷,可以加快每一次運(yùn)行 Gradle 指令時(shí)的生成速度凝垛。當(dāng)只有第二個(gè)參數(shù)被使用時(shí),第一個(gè)參數(shù)是輸出時(shí)會(huì)提示的選項(xiàng)蜓谋,同時(shí)也是官網(wǎng)建議在進(jìn)行開(kāi)發(fā)梦皮、調(diào)試時(shí)使用的選項(xiàng)。如果是使用 Android Studio 來(lái)啟動(dòng) Task 則不用特別設(shè)定孤澎,預(yù)設(shè)就是使用 Daemon 模式届氢。

第二個(gè)參數(shù)是開(kāi)啟 JVM 調(diào)試功能欠窒,讓 Debugger 可以透過(guò) 5005 Port 與 JVM 建立調(diào)試所需的通訊機(jī)制覆旭。address=5005 所指定的數(shù)字可以更改成任意沒(méi)有被占用的 Port,但必須要與 Debugger 所設(shè)定的 Port 相同岖妄。

完成了準(zhǔn)備的工作后型将,接下來(lái)就要讓 Android Studio 的 Debugger 知道調(diào)試目標(biāo)的資訊以便進(jìn)行調(diào)試的工作。點(diǎn)選 Android Studio 的選單功能【Run -> Edit Configurations...】會(huì)出現(xiàn) “Run/Debug Configurations” 窗口荐虐。

在 “Run/Debug Configurations” 窗口左上方點(diǎn)選【+】按鈕七兜,選擇 “Remote” 類型,在下方清單的 Remote 分類就會(huì)多出一個(gè)項(xiàng)目福扬,設(shè)定的畫(huà)面如下方所示腕铸。

所輸入的 “Name” 會(huì)被顯示在 Toolbar 中【Run/Debug Configuration】的下拉菜單中。由于同時(shí)啟動(dòng)多個(gè) Configuration 的運(yùn)行個(gè)體會(huì)有 Port 被占用的問(wèn)題铛碑,所以勾選了 “Single instance only” 選項(xiàng)狠裹。

在 Configuration 選項(xiàng)卡中,上半部是提示要設(shè)定 JVM 進(jìn)行遠(yuǎn)端調(diào)試的參數(shù)范例汽烦,不同時(shí)期的 JDK 有不同的參數(shù)規(guī)格涛菠,每一個(gè)范例右方有復(fù)制按鈕,可以直接復(fù)制到剪貼簿中撇吞,省去打字的麻煩俗冻。

“Settings” 群組內(nèi)的選項(xiàng),如果是在開(kāi)發(fā)階段于本機(jī)進(jìn)行調(diào)試可以使用預(yù)設(shè)的內(nèi)容牍颈。但如果是在系統(tǒng)測(cè)試或正式環(huán)境中調(diào)試迄薄,Host 值應(yīng)該要依據(jù)實(shí)際的 Server 名稱或 IP 位址填入。Port 則是依據(jù) JVM 參數(shù)所下的 address 數(shù)值做調(diào)整煮岁。

完成以上的設(shè)定讥蔽,就可以在 Terminal 窗口中運(yùn)行之前示范并加上參數(shù)的指令死姚,待等 Jetty 啟動(dòng)∏诶海回到源代碼編輯窗口設(shè)定好正確的斷點(diǎn)位置都毒,接著在 Toolbar 中,選擇【Run/Debug Configuration】的下拉清單里剛才設(shè)定的 Remote 類型的項(xiàng)目碰缔,按下右方 Debug 圖標(biāo)的按鈕或 Shift+F9 的快速鍵账劲。

如果一切順利,會(huì)在 Android Studio 下方的 Console 窗口中看到以下訊息:

Connected to the target VM, address: 'localhost:5005', transport: 'socket'

代表 Debugger 已經(jīng)成功的和 Jetty 的 JVM 連結(jié)上金抡,可以開(kāi)始進(jìn)行調(diào)試的作業(yè)瀑焦。此時(shí)就可以啟動(dòng)瀏覽器,輸入網(wǎng)址梗肝,以便運(yùn)行程序榛瓮。當(dāng)運(yùn)行到所設(shè)定的斷點(diǎn)就會(huì)和其他項(xiàng)目一樣,IDE 就會(huì)停在斷點(diǎn)對(duì)應(yīng)的源代碼上巫击,并且可進(jìn)行觀察變量?jī)?nèi)容禀晓、單步執(zhí)行等操作。

到這里雖然工作已經(jīng)可以進(jìn)行了坝锰,但是每一次運(yùn)行調(diào)試都要先下一次指令太麻煩了粹懒,而且當(dāng)源代碼有修改,則 Jetty 要重啟才會(huì)運(yùn)行新的內(nèi)容顷级。然而先前所下的 gradlew 指令會(huì) Block 住 Terminal凫乖,要先按下 Ctrl+C 之后才會(huì)關(guān)閉 Jetty,也才能再下一次啟動(dòng) Jetty 的指令弓颈。

gradlew 指令會(huì) Block 住的情況如果不消除帽芽,對(duì)以后自動(dòng)化生成的作業(yè)也會(huì)造成問(wèn)題、導(dǎo)致自動(dòng)化無(wú)法進(jìn)行翔冀。所幸 Jetty Plugin 也有提供 Daemon 參數(shù)导街,可以消除 jettyRun 運(yùn)行后會(huì) Block 住的情況。為了后續(xù)自動(dòng)化生成也可以一體套用橘蜜,所以在項(xiàng)目文件夾的 build.gradle 里加上以下的內(nèi)容:

jettyRun.daemon = true

加完了之后菊匿,可以先在 Terminal 試看看,果然可以直接回到提示字元计福。但這時(shí)要記得再運(yùn)行 jettyStop 的 Task跌捆,不然 Jetty 沒(méi)有關(guān)閉,下次運(yùn)行 jettyRun 時(shí)會(huì)出現(xiàn) Port 被占用的錯(cuò)誤訊息象颖。

接下來(lái)為了確保 jettyRun 在運(yùn)行前佩厚,Jetty 都有確實(shí)做關(guān)閉的程序,所以要在 build.gradle 里設(shè)定 jettyRun 運(yùn)行之前要先運(yùn)行 jettyStop说订。但目前示范使用的 Gradle 2.2.1 有一個(gè) Bug抄瓦,使用 Daemon 模式的 Jetty 無(wú)法被 jettyStop 正常地關(guān)閉潮瓶,參考官方的解決方法后,必須要新增的內(nèi)容如下:

import org.gradle.api.plugins.jetty.internal.Monitor
[jettyRun, jettyRunWar]*.doLast {
    /**
     * THIS IS A WORKAROUND! THE CURRENT VERSION OF THIS TASK DOESN'T START A WATCHER IN DAEMON MODE
     *
     * If starting the monitor fails, it may be because the jetty task was updated to fix this issue
     * When that happens, we shouldn't need the custom task any more
     *
     * Copied From: AbstractJettyRunTask
     */
    if (getStopPort() != null && getStopPort() > 0 && getStopKey() != null) {
        Monitor monitor = new Monitor(getStopPort(), getStopKey(), server.getProxiedObject());
        monitor.start();
    }
}

[jettyRun, jettyRunWar].each { jetty ->
    jetty.dependsOn jettyStop
}

剩下的就是讓之前設(shè)定好的 Run/Debug Configuration 與 jettyRun 串連起來(lái)钙姊,先回到 “Run/Debug Configurations” 窗口毯辅,并新增一個(gè) Gradle 類型的 Run/Debug Configuration。在 “Name” 的欄位里輸入一個(gè)自己可以識(shí)別的名稱煞额,同時(shí)為了保險(xiǎn)起見(jiàn)勾選了 “Single instance only” 選項(xiàng)思恐,以避免 Debug Port 被不同 JVM Instance 占住了。

“Gradle project” 欄位直接由 Registered Gradle projects 里挑選對(duì)應(yīng)的 Web 項(xiàng)目膊毁,“Tasks” 欄位輸入 jettyRun胀莹,“VM Option”輸入 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50005,或是由 Remote 類型中復(fù)制后貼上婚温。

這里補(bǔ)充說(shuō)明一下描焰,JVM 的參數(shù)也可以設(shè)定在 gradle.property 里,gradle.property 可放在以下幾個(gè)位置:

  • 要套用 JVM 參數(shù)的項(xiàng)目其 build.gradle 所在文件夾
  • 登錄使用者 Home 路徑下的 .gradle 文件夾

但在命令列中指定栅螟,將會(huì)覆蓋過(guò) gradle.property 設(shè)定的內(nèi)容荆秦,先前的 VM Option 則等同于在命令列中指定。選擇在 Run/Debug Configuration 里設(shè)定是因?yàn)橹挥性?IDE 里才有 Debug 的需求嵌巷,如果設(shè)在項(xiàng)目文件夾的 gradle.property 檔案內(nèi)萄凤,當(dāng)檔案被 Checkin 到版控系統(tǒng),可能會(huì)被 CI 系統(tǒng)下載進(jìn)而影響測(cè)試或自動(dòng)化生成的結(jié)果搪哪。所以為了不影響測(cè)試或自動(dòng)化生成,才會(huì)避免在 gradle.property 中進(jìn)行相關(guān)的設(shè)定坪圾。

最后晓折,點(diǎn)選回到最早建立的 Remote 類型項(xiàng)目,在設(shè)定畫(huà)面的右下方空白清單中指定剛才新增 Gradle 類型項(xiàng)目為 Before execute兽泄。完成后漓概,在【Run/Debug Configuration】的下拉清單指定 Remote 類型項(xiàng)目并點(diǎn)選 Toolbar 上的 Debug 圖標(biāo),如果設(shè)定無(wú)誤就可以看到過(guò)程中運(yùn)行了 jettyStop 及 jettyRun病梢,并把 Debugger 連結(jié)到指定的 Port 上一次完成胃珍。所以每次重啟調(diào)試只要一個(gè)按鍵,再切換回瀏覽器重新載入頁(yè)面即可蜓陌。

如果不是要調(diào)試觅彰,只是要看運(yùn)行的結(jié)果,可以將【Run/Debug Configuration】的下拉清單切換成 Gradle 類型的項(xiàng)目后钮热,按下運(yùn)行圖標(biāo)的按鈕即可填抬。

在 GitHub 上有人提供了一個(gè)可以使程序更簡(jiǎn)易的 Plugin 叫 Gretty,有興趣可以自行研究看看隧期。接下來(lái)會(huì)進(jìn)入到系列文章的最后一篇:測(cè)試飒责。

以下為完整的 build.gradle 的內(nèi)容:

apply plugin: "war"
apply plugin: "jetty"

import org.gradle.api.plugins.jetty.internal.Monitor
[jettyRun, jettyRunWar]*.doLast {
    /**
     * THIS IS A WORKAROUND! THE CURRENT VERSION OF THIS TASK DOESN'T START A WATCHER IN DAEMON MODE
     *
     * If starting the monitor fails, it may be because the jetty task was updated to fix this issue
     * When that happens, we shouldn't need the custom task any more
     *
     * Copied From: AbstractJettyRunTask
     */
    if (getStopPort() != null && getStopPort() > 0 && getStopKey() != null) {
        Monitor monitor = new Monitor(getStopPort(), getStopKey(), server.getProxiedObject());
        monitor.start();
    }
}

[jettyRun, jettyRunWar].each { jetty ->
    jetty.dependsOn jettyStop
}

dependencies {
   compile project(":utils")
   compile "javax.servlet:servlet-api:2.5"
}

jettyRun.daemon = true
httpPort = 8080
stopPort = 9090
stopKey = "stopKey"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赘娄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宏蛉,更是在濱河造成了極大的恐慌遣臼,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拾并,死亡現(xiàn)場(chǎng)離奇詭異暑诸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)辟灰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)个榕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人芥喇,你說(shuō)我怎么就攤上這事西采。” “怎么了继控?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵械馆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我武通,道長(zhǎng)霹崎,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任冶忱,我火速辦了婚禮尾菇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘囚枪。我一直安慰自己派诬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布链沼。 她就那樣靜靜地躺著默赂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪括勺。 梳的紋絲不亂的頭發(fā)上瑟俭,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天吱七,我揣著相機(jī)與錄音符衔,去河邊找鬼峻呛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拾氓,可吹牛的內(nèi)容都是我干的冯挎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼房官!你這毒婦竟也來(lái)了趾徽?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤翰守,失蹤者是張志新(化名)和其女友劉穎孵奶,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蜡峰,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡了袁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湿颅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片载绿。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖油航,靈堂內(nèi)的尸體忽然破棺而出崭庸,到底是詐尸還是另有隱情,我是刑警寧澤谊囚,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布怕享,位于F島的核電站,受9級(jí)特大地震影響镰踏,放射性物質(zhì)發(fā)生泄漏函筋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一奠伪、第九天 我趴在偏房一處隱蔽的房頂上張望跌帐。 院中可真熱鬧,春花似錦芳来、人聲如沸含末。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挎袜,卻和暖如春顽聂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盯仪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工紊搪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人全景。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓耀石,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親爸黄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子滞伟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理揭鳞,服務(wù)發(fā)現(xiàn),斷路器梆奈,智...
    卡卡羅2017閱讀 134,704評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,859評(píng)論 6 342
  • 原文鏈接:http://www.dropwizard.io/1.2.0/docs/getting-started....
    Lance_Xu閱讀 911評(píng)論 0 0
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,302評(píng)論 25 707
  • 親愛(ài)的亩钟,這個(gè)世界是有生命的 一乓梨、接受概念,對(duì)世界有覺(jué)知 笑來(lái)老師告訴我們清酥,如果概念不存在扶镀,我們對(duì)概念的客觀存就會(huì)毫...
    青青wh閱讀 100評(píng)論 0 1