2013-07-08 3 views
4

단일 웹 사이트에 액세스하기 위해 webview를 사용하는 JavaFX 응용 프로그램에 대한 자체 프로토콜 처리기를 작성하려고합니다. 내가 지금까지했던사용자 JavaFX WebView 프로토콜 처리기

내 사용자 정의 URLStreamHandlerFactory를

public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory { 

    public URLStreamHandler createURLStreamHandler(String protocol) { 
     System.out.println("Protocol: " + protocol); 
     if (protocol.equalsIgnoreCase("http") || protocol.equalsIgnoreCase("https")) { 
      return new MyURLStreamHandler(); 
     } else { 
      return new URLStreamHandler() { 
       @Override 
       protected URLConnection openConnection(URL u) throws IOException { 
        return new URLConnection(u) { 
         @Override 
         public void connect() throws IOException { 
         } 
        }; 
       } 
      }; 
     } 
    } 
} 

내 사용자 정의 URLStreamHandler의

public class MyURLStreamHandler extends java.net.URLStreamHandler{ 

    protected HttpURLConnection openConnection(URL u){ 
     MyURLConnection q = new MyURLConnection(u); 
     return q; 
    }  
} 

내 사용자 정의 HttpURLConnection의

public class MyURLConnection extends HttpURLConnection { 

    static int defaultPort = 443; 
    InputStream in; 
    OutputStream out; 
    Socket s; 

    publicMyURLConnection(URL url) { 
     super(url); 
     try { 
      setRequestMethod("POST"); 
     } catch (ProtocolException ex) { 
      ex.printStackTrace(); 
     } 
    } 

    public void setRequestProperty(String name, String value){ 
     super.setRequestProperty(name, value); 
     System.out.println("Namee: " + name); 
     System.out.println("Value: " + value); 
    } 

    public String getRequestProperty(String name){ 
     System.out.println("GET REQUEST: "); 
     return super.getRequestProperty(name); 
    } 

    public OutputStream getOutputStream() throws IOException { 
     OutputStream os = super.getOutputStream(); 
     System.out.println("Output: " + os); 
     return os; 
    } 

    public InputStream getInputStream() throws IOException { 
     InputStream is = super.getInputStream(); 
     System.out.println("INout stream: " + is); 
     return is; 
    } 

    @Override 
    public void connect() throws IOException { 
    } 

    @Override 
    public void disconnect() { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    @Override 
    public boolean usingProxy() { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

나는 다음과 같은 오류가 응용 프로그램을 실행할 때 일부 헤더를 설정하는 것 같아요.

Jul 08, 2013 11:09:04 AM com.sun.webpane.webkit.network.URLLoader doRun 
WARNING: Unexpected error 
java.net.UnknownServiceException: protocol doesn't support input 
at java.net.URLConnection.getInputStream(URLConnection.java:839) 
at qmed.QMedURLConnection.getInputStream(MyURLConnection.java:67) 
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468) 
at com.sun.webpane.webkit.network.URLLoader.receiveResponse(URLLoader.java:383) 
at com.sun.webpane.webkit.network.URLLoader.doRun(URLLoader.java:142) 
at com.sun.webpane.webkit.network.URLLoader.access$000(URLLoader.java:44) 
at com.sun.webpane.webkit.network.URLLoader$1.run(URLLoader.java:106) 
at com.sun.webpane.webkit.network.URLLoader$1.run(URLLoader.java:103) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.webpane.webkit.network.URLLoader.run(URLLoader.java:103) 
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
at java.lang.Thread.run(Thread.java:724) 

내가 원하는 것은 주어진 요청에 대한 응답을 받고 그 이진 데이터를 읽는 것입니다. 프로토콜이 기본 프로토콜과 정확히 같은 방식으로 작동하고 지정된 응답음의 이진 데이터 만 확인하려고합니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

응용 프로그램이 URLConnections의 단점을 모두 수행하고 있습니다. 프로토콜이 http 또는 https 인 경우 사용자 정의 URLConnection 클래스로 HTTPURLConnection을 사용하고 MyURLStreamHandlerFactory에서 수행하는 것처럼 다른 프로토콜을 사용할 때 기본 URLStreamHandler를 시작하는 것이 맞습니까? 모든 프로토콜을 동일하게 처리하기 위해 MYURLConnection의 기본 URLConnection 클래스를 확장해야합니까?

어떤 도움이 많이

당신에게

감사이 프로젝트 위협하는 문제로 감상 할 수있다

답변

3

그것은 수도있을 당신이없는 모든하다는 setDoInput(true) 또는 (즉, 내가 무슨 짓을했는지) getDoInput()을 무시하고 true를 반환 .

그건 내 작업 솔루션 체크 아웃 도움이되지 않는 경우 :

MyURLStreamHandlerFactory :

import java.net.URLStreamHandler; 
import java.net.URLStreamHandlerFactory; 

public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory 
{ 

    public URLStreamHandler createURLStreamHandler(String protocol) 
    { 
     if (protocol.equals("myapp")) 
     { 
      return new MyURLHandler(); 
     } 
     return null; 
    } 

} 

등록 공장 :

URL.setURLStreamHandlerFactory(new MyURLStreamHandlerFactory()); 

MyURLHandler :

import java.io.IOException; 
import java.net.URL; 
import java.net.URLConnection; 
import java.net.URLStreamHandler; 

public class MyURLHandler extends URLStreamHandler 
{ 

    @Override 
    protected URLConnection openConnection(URL url) throws IOException 
    { 
     return new MyURLConnection(url); 
    } 

} 

MyURLConnection : 작동하는 MyURLConnection

import java.io.*; 
import java.net.SocketTimeoutException; 
import java.net.URL; 
import java.net.URLConnection; 

/** 
* Register a protocol handler for URLs like this: <code>myapp:///pics/sland.gif</code><br> 
*/ 
public class MyURLConnection extends URLConnection 
{ 

    private byte[] data; 

    @Override 
    public void connect() throws IOException 
    { 
     if (connected) 
     { 
      return; 
     } 
     loadImage(); 
     connected = true; 
    } 

    public String getHeaderField(String name) 
    { 
     if ("Content-Type".equalsIgnoreCase(name)) 
     { 
      return getContentType(); 
     } 
     else if ("Content-Length".equalsIgnoreCase(name)) 
     { 
      return "" + getContentLength(); 
     } 
     return null; 
    } 

    public String getContentType() 
    { 
     String fileName = getURL().getFile(); 
     String ext = fileName.substring(fileName.lastIndexOf('.')); 
     return "image/" + ext; // TODO: switch based on file-type 
    } 

    public int getContentLength() 
    { 
     return data.length; 
    } 

    public long getContentLengthLong() 
    { 
     return data.length; 
    } 

    public boolean getDoInput() 
    { 
     return true; 
    } 

    public InputStream getInputStream() throws IOException 
    { 
     connect(); 
     return new ByteArrayInputStream(data); 
    } 

    private void loadImage() throws IOException 
    { 
     if (data != null) 
     { 
      return; 
     } 
     try 
     { 
      int timeout = this.getConnectTimeout(); 
      long start = System.currentTimeMillis(); 
      URL url = getURL(); 

      String imgPath = url.toExternalForm(); 
      imgPath = imgPath.startsWith("myapp://") ? imgPath.substring("myapp://".length()) : imgPath.substring("myapp:".length()); // attention: triple '/' is reduced to a single '/' 

      // this is my own asynchronous image implementation 
      // instead of this part (including the following loop) you could do your own (synchronous) loading logic 
      MyImage img = MyApp.getImage(imgPath); 
      do 
      { 
       if (img.isFailed()) 
       { 
        throw new IOException("Could not load image: " + getURL()); 
       } 
       else if (!img.hasData()) 
       { 
        long now = System.currentTimeMillis(); 
        if (now - start > timeout) 
        { 
         throw new SocketTimeoutException(); 
        } 
        Thread.sleep(100); 
       } 
      } while (!img.hasData()); 
      data = img.getData(); 
     } 
     catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public OutputStream getOutputStream() throws IOException 
    { 
     // this might be unnecessary - the whole method can probably be omitted for our purposes 
     return new ByteArrayOutputStream(); 
    } 

    public java.security.Permission getPermission() throws IOException 
    { 
     return null; // we need no permissions to access this URL 
    } 

} 

일부 부품이 필요하지 않을 수도 있지만, 이런 식으로 나를 위해 작동합니다.자바 FX의 웹보기에서

사용법 : 권한에 대한

<img src="myapp:///pics/image.png"/> 

참고 :

나는 AllPermissions 위의 코드 내 테스트와 애플릿을 사용했다. setFactory 권한이없는 것처럼이 작동하지 않습니다 -Applet 샌드 박스에서

.

+0

좋은 답변입니다. 지금까지 나는 그것을 나의 필요에 가장 가깝게 발견했다. 하지만 내가 원하는 것은 모든 프로토콜을 포착하는 것이다. HTTP, HTTPS, file : // 개발자 콘솔에서 모든 요청을 볼 수있는 것과 같습니다. –

+0

이것으로 무엇을 이루고자합니까? 어쩌면 네트워크 스니퍼/분석기 도구로 원하는 작업을 수행 할 수 있습니다. –

+0

또 다른 도움이 될만한 것은 FirebugLite를 사용하는 것입니다 :''-이 코드를 귀하의 WebView 페이지 및 WebView에서 페이지를 디버깅 할 수 있습니다. 불행히도 FBLite에는 네트워크 탭이 없습니다. –

-1

질문과 직접적인 관련이 없지만 질문 자체가 쓸모 없게 될 수도 있습니다. 자바 SE 6 업데이트 10 Java 애플릿으로

올바르게 crossdomain.xml에와 을 설정하는 모든 도메인과 포트의 리소스에 액세스하기 위해 지원합니다.

이렇게하면 필요한 모든 리소스에 액세스 할 수 있으므로 자체 프로토콜을 등록하는 이유가 더 이상 쓸모 없게 될 수 있습니다.

또 다른 아이디어는 : 네트워크 스니퍼의 종류를 만들려고한다면, 그런 작업을 위해 설계된 네트워크 스니퍼/분석기 프로그램을 직접 사용하지 않는 이유는 무엇입니까?

-2

Java 제어판에서 로깅 및 추적을 활성화하면 Java 콘솔이 WebView에서 실행 된 시도 및 실행 된 모든 네트워크 호출을 인쇄합니다.

모든 HTTP & HTTPS 호출과 그 리턴 코드 + 쿠키 데이터를 볼 수 있습니다. 다른 프로토콜 연결도 표시 될 수 있지만이 프로토콜을 통한 데이터 전송은 아닙니다.

브라우저의 애플릿에 적용됩니다. 다른 컨텍스트에서이 옵션이 필요한 경우 명령 줄 매개 변수를 전달하여 동일한 옵션을 활성화 할 수 있습니다.