JavaFx WebView使用研究

one發表於2021-12-19

原文: JavaFx WebView使用研究 | Stars-One的雜貨小窩

本篇是基於TornadoFx框架的基礎研究的,示例程式碼都是Kotlin版本,各位可以看著參考下

WebView中比較重要的是其內建的engine物件,後續的相關操作都是通過這個物件進行管理

載入網頁

使用WebView內建的engine物件的load()方法進行網頁的載入

class TestView : View("My View") {
    var webView by singleAssign<WebView>()
    override val root = vbox {
        setPrefSize(600.0,500.0)
        webView = webview {

        }
        webView.engine.load("https://stars-one.site")
    }
}

獲取頁面地址

獲取當前頁面地址直接獲取location屬性值即可

val currentUrl = engine.location

上述是直接獲取頁面地址,除此之外,engine還提供了一個頁面地址變化的監聽器,如下程式碼:

engine.locationProperty().addListener { observable, oldValue, newValue ->
    println("之前的網址: ${oldValue}")
    println("新載入網址: ${newValue}")
}

獲取頁面內容

val htmlStr = webView.engine.document.ownerDocument.textContent

也可以設定個監聽器,每次頁面發生跳轉的時候,會觸發監聽的回撥,來獲取新的頁面內容資料,程式碼如下:

engine.documentProperty().addListener { observable, oldValue, newValue ->
    //頁面Document
    val htmlStr = oldValue.ownerDocument.textContent
    
    //這裡如果Html是有動態載入iframe,是沒法拿到iframe載入的資料內容的,即使你再網頁上已經看到載入完畢了!!
}

PS:需要注意的是,如果html中的使用js去動態載入iframe的內容,使用上述方法並不能獲取iframe內載入的文件內容

cookie的讀寫

WebView中,有個cookie處理器,預設是 com.sun.webkit.network.CookieManager,這個我們可以拿到cookie的字串,但是沒法去設定cookie

研究的時候全網找了下方法,算是曲線救國解決了(也不知道合不合理,具體就沒過多研究了)

在webview載入網址url之前,我們得先使用CookieManager.setDefault()方法去設定一個我們定義好的物件CookieManager(java.net包中)

之後,想要獲取Cookie即可呼叫CookieHandler.getDefault()方法獲取

獲取cookie

val cookieManager = CookieHandler.getDefault() as CookieManager
val cookieStore = cookieManager.cookieStore

val map = mutableMapOf<URI, List<HttpCookie>>()
//根據域名去找域名下的cookie
cookieStore.urIs.forEach {
    //如果想要獲取指定域名,建議在這裡加個判斷條件,過濾一下域名
    val httpCookieList = cookieStore[it]
    map[it] = httpCookieList
}

關於cookie儲存和設定

fun saveCookie() {
    val cookieManager = CookieHandler.getDefault() as CookieManager
    val cookieStore = cookieManager.cookieStore

    val map = mutableMapOf<URI, List<HttpCookie>>()
    cookieStore.urIs.forEach {
        val httpCookieList = cookieStore[it]
        map[it] = httpCookieList
    }
    val localCookie = LocalCookie(map)
    
    //將實體類的資料轉為json字串進行儲存
    val cookieManagerStr = Gson().toJson(localCookie)
    
    //下面是用了tornadofx內建的儲存,將字串寫入了指定的配置檔案中,可以替換成實現的步驟
    //之後首次進來需要讀取該檔案,將cookie設定即可
    config["cookieManagerStr"] = cookieManagerStr
    config.save()
}

//實體類
data class LocalCookie(val map: Map<URI, List<HttpCookie>>)

進來時候cookie的設定:

fun loadCookie() {
    //1.讀檔案將json字串讀取
    val buffer = StringBuffer()
    val json = config.string("cookieManagerStr", "")
    
    //2.建立一個CookieManager(這裡要匯入java.net包中)
    val myCookie = CookieManager()

    if (json.isNotBlank()) {
        //3. 迴圈將資料重新寫入到CookieManager中
        val localCookie = Gson().fromJson(json, LocalCookie::class.java)
        localCookie.map.forEach { key, list ->
            list.forEach {
                //注意:這裡是判斷cookie是否過期,過期就不新增到裡面了
                if (!it.hasExpired()) {
                    myCookie.cookieStore.add(key, it)
                }
            }
        }
    }
    //4.設定cookie(如果沒有cookie的話,這樣設定也沒事)
    CookieManager.setDefault(myCookie)
}

cookie的妙用:

某些網站中某些頁面需要登入才能訪問的的,其實本質上就是在訪問網頁前新增了cookie的引數

我們可以先使用webview訪問其網頁,讓使用者掃碼進行登入,之後獲取cookie的數值,拼接成字串,然後訪問那些需要才能訪問的網頁

訪問網頁的時候請求頭的header中帶上cookie屬性(具體設定可參照你使用的網路框架),之後即可繞過登入的限制

相關文章