설명
나는이 문제를했고 내가 어떤 AJAX 요청을 처리하는 데 사용 sun.net.www.protocol.http.HttpURLConnection
내 자신의 구현을 제공하여 해결했습니다. 편리하게 AjaxHttpURLConnection
이라고 불리는 내 클래스는 getInputStream()
함수에 후크하지만 원래 입력 스트림을 반환하지 않습니다. 대신 PipedInputStream
의 인스턴스를 WebEngine
에 반환합니다. 그런 다음 원래 입력 스트림에서 오는 모든 데이터를 읽고이를 파이프 된 스트림으로 전달합니다. 이 방법은, 내가 2 개 혜택을 얻을 :
마지막 바이트를받은 따라서 AJAX 요청이 완전히 처리되었을 때 내가 아는
- .
- 들어오는 모든 데이터를 가져 와서 이미 작업하고 있습니다 (원하는 경우).
예
먼저
,
당신은 기본 일 대신 URLConnection의 구현를 사용하는 자바 말할해야합니다. 그렇게하려면 자신의 버전 인
URLStreamHandlerFactory
을 제공해야합니다. 이 주제에 관해서는 SO (예 :
this one) 또는 Google을 통해 많은 스레드를 찾을 수 있습니다. 공장 인스턴스를 설정하려면
main
메소드 초기에 다음을 입력하십시오. 이것은 내 모습과 같습니다.
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
public class MyApplication extends Application {
// ...
public static void main(String[] args) {
URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
public URLStreamHandler createURLStreamHandler(String protocol) {
if ("http".equals(protocol)) {
return new MyUrlConnectionHandler();
}
return null; // Let the default handlers deal with whatever comes here (e.g. https, jar, ...)
}
});
launch(args);
}
}
둘째, 우리는 URLConnection
의 유형을 사용할 수있는 프로그램을 알려줍니다 그 Handler
우리 자신을 마련한다.
import java.io.IOException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import sun.net.www.protocol.http.Handler;
import sun.net.www.protocol.http.HttpURLConnection;
public class MyUrlConnectionHandler extends Handler {
@Override
protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
if (url.toString().contains("ajax=1")) {
return new AjaxHttpURLConnection(url, proxy, this);
}
// Return a default HttpURLConnection instance.
return new HttpURLConnection(url, proxy);
}
}
마지막으로, 여기에 AjaxHttpURLConnection
이옵니다.
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.Proxy;
import java.net.URL;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.io.IOUtils;
import sun.net.www.protocol.http.Handler;
import sun.net.www.protocol.http.HttpURLConnection;
public class AjaxHttpURLConnection extends HttpURLConnection {
private PipedInputStream pipedIn;
private ReentrantLock lock;
protected AjaxHttpURLConnection(URL url, Proxy proxy, Handler handler) {
super(url, proxy, handler);
this.pipedIn = null;
this.lock = new ReentrantLock(true);
}
@Override
public InputStream getInputStream() throws IOException {
lock.lock();
try {
// Do we have to set up our own input stream?
if (pipedIn == null) {
PipedOutputStream pipedOut = new PipedOutputStream();
pipedIn = new PipedInputStream(pipedOut);
InputStream in = super.getInputStream();
/*
* Careful here! for some reason, the getInputStream method seems
* to be calling itself (no idea why). Therefore, if we haven't set
* pipedIn before calling super.getInputStream(), we will run into
* a loop or into EOFExceptions!
*/
// TODO: timeout?
new Thread(new Runnable() {
public void run() {
try {
// Pass the original data on to the browser.
byte[] data = IOUtils.toByteArray(in);
pipedOut.write(data);
pipedOut.flush();
pipedOut.close();
// Do something with the data? Decompress it if it was
// gzipped, for example.
// Signal that the browser has finished.
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
} finally {
lock.unlock();
}
return pipedIn;
}
}
또한 고려
- 여러
WebEngine
객체를 사용하는 경우, 실제로 브라우저가로드를 완료 한 URLConnection
따라서 오픈 어느 말할 힘들 수 있습니다.
- 당신은 내가 HTTP 연결로만 부를 수 있다는 것을 눈치 챘을 것입니다. 나는 나의 접근법이 https 등으로 얼마나 멀리 옮겨 갈 수 있는지 테스트하지 않았다. (전문가가 아닌 : O).
- 당신이 본 것처럼, 내
AjaxHttpURLConnection
을 실제로 사용할시기를 아는 유일한 방법은 해당 URL에 ajax=1
이 포함 된 경우입니다. 내 경우에는 충분했다. 그러나 html과 http와는별로 좋지 않으므로 WebEngine
이 AJAX 요청을 다른 방식으로 만들 수 있는지 여부를 알지 못합니다 (예 : 헤더 필드?). 확실하지 않은 경우, 수정 된 URL 연결의 인스턴스를 항상 반환 할 수는 있지만 이는 물론 약간의 오버 헤드를 의미합니다.
- 처음에 설명한 것처럼 입력 스트림에서 검색 한 데이터로 즉시 작업 할 수 있습니다.
WebEngine
에서 보내는 요청 데이터를 비슷한 방식으로 가져올 수 있습니다. getOutputStream()
함수를 랩핑하고 다른 중간 스트림을 보내서 무엇이든지 보내고 원래의 출력 스트림으로 전달하십시오. HTTPS에 대해 이렇게이 @의 dadoosh의 대답의 확장
동일한 문제가 발생합니다. 솔루션을 찾을 수 있었습니까? – wib
@wib : 불행히도, 나는 해킹을 시도했지만 문제는 웹 엔진이 구축 된 라이브러리에 더 깊게 자리 잡고 있습니다. 나를 위해 가장 잘 작동하는 해킹은 javafx 스레드를 "잠자기"로 잠시 멈추게하고 잠시 js가 완료 될 때까지 기다리는 것이 었습니다 ... – Warkst
나는 그 일을 생각했지만 신뢰할 수있는 인터넷 연결에 크게 의존합니다. . 그게 지금 제일 좋은 해결책 인 것 같아. – wib