自定义JavaFX WebView协议处理程序 [英] Custom JavaFX WebView Protocol Handler

查看:171
本文介绍了自定义JavaFX WebView协议处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为使用webview访问单个网站的JavaFX应用程序编写自己的协议处理程序。到目前为止我做了什么

I am trying to write my own protocol handler for a JavaFX application that uses webview to access a single website. What I have done so far

我的自定义URLStreamHandlerFactory

My custom 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

My custom URLStreamHandler

public class MyURLStreamHandler extends java.net.URLStreamHandler{

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

我的自定义HttpURLConnection

My custom 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."); 
    }

当我运行应用程序时,我得到以下错误,但它似乎设置了一些标题

When I run the application I get the following error althouhg it seems to set some headers

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)

我想做的就是获取给定的响应请求并读取其二进制数据。我希望协议的行为与默认协议完全相同,并且只检查给定respone的二进制数据。我究竟做错了什么?

All I want to do is get the response back for a given request and reads its binary data. I want the protocol to behave exactly the same way as the default one and only check the binary data of a given respone. What am I doing wrong?

应用程序正在执行URLConnections的所有短路。当协议是http或https时使用HTTPURLConnection作为我的自定义URLConnection类是正确的,并且当使用其他协议时启动默认的URLStreamHandler,就像我在MyURLStreamHandlerFactory中所做的那样?我应该只扩展MYURLConnection中的默认URLConnection类来处理所有协议吗?

The application is doing all shorts of URLConnections. Is it correct to use a HTTPURLConnection as my custom URLConnection class when the protocol is http or https and start a default URLStreamHandler when other protocols are used like I am doing in MyURLStreamHandlerFactory? Should I just extend the default URLConnection class in MYURLConnection to handle all protocols the same?

任何帮助都会受到赞赏,因为这是一个项目威胁问题

Any help would be much appreciated as this is a project threatening problem

谢谢

推荐答案

可能你所缺少的只是 setDoInput(true)或覆盖 getDoInput()并返回true(这就是我所做的)。

It might be that all you are missing is a setDoInput(true) or override getDoInput() and return true (that's what i did).

如果这无法帮助我查看我的工作解决方案:

If that does not help check out my working solution:

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:

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
    }

}

MyURLConnection 的某些部分可能不是必须的,但是这样对我有用。

Some parts of MyURLConnection might not be necessary for it to work, but like this it works for me.

JavaFX WebView中的用法:

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

关于权限的说明:

我使用带有 AllPermissions 的applet进行上述代码的测试。

I used an applet with AllPermissions for my test with the above code.

Sandbox -Applet这不起作用,因为缺少 setFactory 权限。

In a Sandbox-Applet this won't work, as the setFactory permission is missing.

这篇关于自定义JavaFX WebView协议处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆