我正在尝试为使用webview访问单个网站的JavaFX应用程序编写自己的协议处理程序。到目前为止我做了什么
我的自定义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)
我想做的就是获取给定请求的响应并读取其二进制数据。我希望协议的行为与默认协议完全相同,并且只检查给定respone的二进制数据。我究竟做错了什么?
应用程序正在执行URLConnections的所有短路。当协议是http或https时,使用HTTPURLConnection作为我的自定义URLConnection类是正确的吗?当我在MyURLStreamHandlerFactory中使用其他协议时启动默认的URLStreamHandler是正确的吗?我应该只扩展MYURLConnection中的默认URLConnection类来处理所有协议吗?
任何帮助都会受到高度赞赏,因为这是一个项目威胁问题
谢谢
答案 0 :(得分: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:强>
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
的某些部分可能没有必要使用它,但像这样对我有效。
JavaFX WebView中的用法:
<img src="myapp:///pics/image.png"/>
关于权限的说明:
我使用带有 AllPermissions 的applet进行上述代码测试。
在 Sandbox -Applet中,这将无效,因为缺少setFactory
权限。
答案 1 :(得分:-1)
这与提出的问题没有直接关系,但可能会使问题本身过时。
使用Java SE 6 Update 10 Java Applets支持访问使用crossdomain.xml 正确设置的任何域和端口上的资源。
这样,注册自己的协议的原因可能会过时,因为您可以访问所需的所有资源。
另一个想法是:如果您正在尝试创建一种网络嗅探器,为什么不直接使用专为此类任务设计的网络嗅探器/分析器程序?
答案 2 :(得分:-2)
通过激活Java控制面板中的日志记录和跟踪,您的Java控制台将打印所有尝试并执行网络调用,包括来自WebView的调用。
您可以看到所有HTTP&amp; HTTPS调用及其返回代码+ cookie数据。 您可能还会看到其他协议连接,但可能不会通过它们发送任何数据。
这适用于浏览器中的Applet。 如果您在不同的上下文中需要它,可以通过传递命令行参数来激活相同的选项。