在clojure中指定对象类

Gal*_*ude 1 clojure jsoup clojure-java-interop

我不想刮一个网站,这需要我登录.我决定用Jsoup来做这件事.我无法正确地将这行代码"翻译"到Clojure:

Connection.Response loginForm = Jsoup.connect("**url**")
        .method(Connection.Method.GET)
        .execute();
Run Code Online (Sandbox Code Playgroud)

如果没有Connection.Response在我的Clojure代码中指定类,则连接具有类jsoup.helper.HttpConnect,该类缺少会话中的cookie所需的方法.

到目前为止,我已经提出了以下Clojure代码:

(import (org.jsoup Jsoup Connection
               Connection$Response Connection$Method))
(do
 (def url "*URL*")
 (def res (doto (org.jsoup.Jsoup/connect url)
   (.data "username" "*USERNAME*")
   (.data "password" "*PASSWORD")
   (.method Connection$Method/POST)
   (.execute)))
 (type res))
Run Code Online (Sandbox Code Playgroud)

Pio*_*dyl 5

问题是你在使用线程宏的doto地方使用->:

(let [url "*URL*"]
  (-> url
      (org.jsoup.Jsoup/connect)
      (.data "username" "*USERNAME*")
      (.data "password" "*PASSWORD*")
      (.method "Connection$Method/POST)
      (.execute)))
Run Code Online (Sandbox Code Playgroud)

doto当您需要设置一个Java对象时,通常会使用表单,该对象提供类似于setter的方法,void并且会阻止您使用线程.

(doto (SomeClass.)
  (.setA 1)
  (.setB 2)
  (.execute))
Run Code Online (Sandbox Code Playgroud)

翻译成:

(let [obj (SomeClass.)]
  (.setA obj 1)
  (.setB obj 2)
  (.execute obj)
  obj)
Run Code Online (Sandbox Code Playgroud)

如您所见doto,不会返回最后一个方法调用的结果,而是返回作为其第一个参数提供的对象(SomeClass在本例中为object).因此,您当前的代码返回Jsoup/connect方法创建的对象(jsoup.helper.HttpConnect如您所注意到的),而不是方法调用的Connection.Response结果execute().

你需要的是:

(-> (SomeClass.)
    (.withA 1)
    (.withB 2)
    (.execute))
Run Code Online (Sandbox Code Playgroud)

with*返回的构建器方法在哪里this而不是void.

以上线程表相当于:

(.execute
  (.withB
    (.withA
      (SomeClass.)
      1)
    2))
Run Code Online (Sandbox Code Playgroud)