日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

对Java的URL类支持的协议进行扩展的方法

發(fā)布時(shí)間:2023/12/3 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对Java的URL类支持的协议进行扩展的方法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自? ?對(duì)Java的URL類支持的協(xié)議進(jìn)行擴(kuò)展的方法

?JAVA默認(rèn)提供了對(duì)file,ftp,gopher,http,https,jar,mailto,netdoc協(xié)議的支持。當(dāng)我們要利用這些協(xié)議來創(chuàng)建應(yīng)用時(shí),主要會(huì)涉及到如下幾個(gè)類:java.net.URL、java.net.URLConnection、InputStream。URL類默認(rèn)支持上述協(xié)議,但是有時(shí)候我們想自定義協(xié)議,怎么辦呢?


Java提供了三種方法可以支持這個(gè)擴(kuò)展

1、URL.setURLStreamHandlerFactory(URLStreamHandlerFactory)

? ? ? URLStreamHandlerFactory(java.net.URLStreamHandlerFactory),這是一個(gè)接口,定義如下:

package java.net; /** * This interface defines a factory for {@code URL} stream * protocol handlers. * <p> * It is used by the {@code URL} class to create a * {@code URLStreamHandler} for a specific protocol. * * @author Arthur van Hoff * @see java.net.URL * @see java.net.URLStreamHandler * @since JDK1.0 */ public interface URLStreamHandlerFactory { /** * Creates a new {@code URLStreamHandler} instance with the specified * protocol. * * @param protocol the protocol ("{@code ftp}", * "{@code http}", "{@code nntp}", etc.). * @return a {@code URLStreamHandler} for the specific protocol. * @see java.net.URLStreamHandler */ URLStreamHandler createURLStreamHandler(String protocol); }

此接口需要實(shí)現(xiàn)createURLStreamHandler(String protocol)方法,參數(shù)protocol為協(xié)議名稱,返回URLStreamHandler( java.net.URLStreamHandler )抽象類,抽象方法定義如下:

abstract protected URLConnection openConnection(URL u) throws IOException; 參數(shù)u為URL類型,URL.openConnection間接調(diào)用這個(gè)方法,返回URLConnection,然后可以獲取InputStream進(jìn)而獲取相應(yīng)的數(shù)據(jù)(資源)
示例如下:
URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() { @Override public URLStreamHandler createURLStreamHandler(String protocol) { if("json".equals(protocol)){ return new URLStreamHandler(){ @Override protected URLConnection openConnection(URL url) throws IOException { return new URLConnection(url){ public InputStream getInputStream() throws IOException { return new FileInputStream("d:/aaaa.txt"); } @Override public void connect() throws IOException { //建立連接 } }; } }; } else return null; } }); URL url = new URL("json://json.url.com"); InputStream in = url.openConnection().getInputStream(); System.out.println(in.read());

上述代碼判斷如果協(xié)議(protocal)為json,則返回一個(gè)自定義的URLStreamHandler,否則返回null,對(duì)應(yīng)其他Java本身已經(jīng)支持的協(xié)議會(huì)不會(huì)造成影響呢?

我們且看URL的一個(gè)構(gòu)造方法(URL(String protocol, String host, int port, String file,URLStreamHandler handler) 中類似):

public URL(URL context, String spec, URLStreamHandler handler) throws MalformedURLException { String original = spec; int i, limit, c; int start = 0; String newProtocol = null; boolean aRef=false; boolean isRelative = false; // Check for permission to specify a handler if (handler != null) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkSpecifyHandler(sm); } } try { limit = spec.length(); while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { limit--; //eliminate trailing whitespace } while ((start < limit) && (spec.charAt(start) <= ' ')) { start++; // eliminate leading whitespace } if (spec.regionMatches(true, start, "url:", 0, 4)) { start += 4; } if (start < spec.length() && spec.charAt(start) == '#') { /* we're assuming this is a ref relative to the context URL. * This means protocols cannot start w/ '#', but we must parse * ref URL's like: "hello:there" w/ a ':' in them. */ aRef=true; } for (i = start ; !aRef && (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) { if (c == ':') { String s = spec.substring(start, i).toLowerCase(); if (isValidProtocol(s)) { newProtocol = s; start = i + 1; } break; } } // Only use our context if the protocols match. protocol = newProtocol; if ((context != null) && ((newProtocol == null) || newProtocol.equalsIgnoreCase(context.protocol))) { // inherit the protocol handler from the context // if not specified to the constructor if (handler == null) { handler = context.handler; } // If the context is a hierarchical URL scheme and the spec // contains a matching scheme then maintain backwards // compatibility and treat it as if the spec didn't contain // the scheme; see 5.2.3 of RFC2396 if (context.path != null && context.path.startsWith("/")) newProtocol = null; if (newProtocol == null) { protocol = context.protocol; authority = context.authority; userInfo = context.userInfo; host = context.host; port = context.port; file = context.file; path = context.path; isRelative = true; } } if (protocol == null) { throw new MalformedURLException("no protocol: "+original); } // Get the protocol handler if not specified or the protocol // of the context could not be used if (handler == null && (handler = getURLStreamHandler(protocol)) == null) { throw new MalformedURLException("unknown protocol: "+protocol); } this.handler = handler; i = spec.indexOf('#', start); if (i >= 0) { ref = spec.substring(i + 1, limit); limit = i; } /* * Handle special case inheritance of query and fragment * implied by RFC2396 section 5.2.2. */ if (isRelative && start == limit) { query = context.query; if (ref == null) { ref = context.ref; } } handler.parseURL(this, spec, start, limit); } catch(MalformedURLException e) { throw e; } catch(Exception e) { MalformedURLException exception = new MalformedURLException(e.getMessage()); exception.initCause(e); throw exception; } }

代碼87行,調(diào)用了getURLStreamHandler(protocol),此方法:

static URLStreamHandler getURLStreamHandler(String protocol) { URLStreamHandler handler = handlers.get(protocol); if (handler == null) { boolean checkedWithFactory = false; // Use the factory (if any) if (factory != null) { handler = factory.createURLStreamHandler(protocol); checkedWithFactory = true; } // Try java protocol handler if (handler == null) { String packagePrefixList = null; packagePrefixList = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction( protocolPathProp,"")); if (packagePrefixList != "") { packagePrefixList += "|"; } // REMIND: decide whether to allow the "null" class prefix // or not. packagePrefixList += "sun.net.www.protocol"; StringTokenizer packagePrefixIter = new StringTokenizer(packagePrefixList, "|"); while (handler == null && packagePrefixIter.hasMoreTokens()) { String packagePrefix = packagePrefixIter.nextToken().trim(); try { String clsName = packagePrefix + "." + protocol + ".Handler"; Class<?> cls = null; try { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { ClassLoader cl = ClassLoader.getSystemClassLoader(); if (cl != null) { cls = cl.loadClass(clsName); } } if (cls != null) { handler = (URLStreamHandler)cls.newInstance(); } } catch (Exception e) { // any number of exceptions can get thrown here } } } synchronized (streamHandlerLock) { URLStreamHandler handler2 = null; // Check again with hashtable just in case another // thread created a handler since we last checked handler2 = handlers.get(protocol); if (handler2 != null) { return handler2; } // Check with factory if another thread set a // factory since our last check if (!checkedWithFactory && factory != null) { handler2 = factory.createURLStreamHandler(protocol); } if (handler2 != null) { // The handler from the factory must be given more // importance. Discard the default handler that // this thread created. handler = handler2; } // Insert this handler into the hashtable if (handler != null) { handlers.put(protocol, handler); } } } return handler; }

代碼段

if (factory != null) {

handler = factory.createURLStreamHandler(protocol);
checkedWithFactory = true;
}

這一段是從factory中獲取相應(yīng)協(xié)議的URLStreamHandler,如果獲取不到,則從另一渠道獲得(即不會(huì)對(duì)java已經(jīng)支持的協(xié)議造成影響),就是我們講的第2種方法

各個(gè)構(gòu)造方法的調(diào)用關(guān)系代碼如下:

//#1 public URL(String spec) throws MalformedURLException { this(null, spec);//調(diào)用#2 URL(URL context, String spec) } //#2 public URL(URL context, String spec) throws MalformedURLException { this(context, spec, null);調(diào)用#6 URL(URL context, String spec, URLStreamHandler handler) } //#3 public URL(String protocol, String host, int port, String file) throws MalformedURLException { this(protocol, host, port, file, null);//調(diào)用#6 RL(String protocol, String host, int port, String file,URLStreamHandler handler) } //#4 public URL(String protocol, String host, String file) throws MalformedURLException { this(protocol, host, -1, file);//調(diào)用#3 URL(String protocol, String host, int port, String file) } //#5 public URL(String protocol, String host, int port, String file, URLStreamHandler handler) throws MalformedURLException{ //.... } //#6 public URL(URL context, String spec, URLStreamHandler handler) throws MalformedURLException{ //.... } //可以看出,實(shí)質(zhì)性邏輯都在#5和#6方法


2、?通過?JVM?啟動(dòng)參數(shù)?-Djava.protocol.handler.pkgs來設(shè)置?URLStreamHandler?實(shí)現(xiàn)類的包路徑

比如-D java.protocol.handler.pkgs=com.myprotocol.pkgs0|com.myprotocol.pkgs1,多個(gè)用|分割,java默認(rèn)的包為sun.net.www.protocol,設(shè)置了這個(gè)參數(shù),會(huì)拼接在默認(rèn)的包之后,即sun.net.www.protocol|com.myprotocol.pkgs0|com.myprotocol.pkgs1

看這段代碼

if (handler == null) { String packagePrefixList = null; packagePrefixList = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction( protocolPathProp,""));//protocolPathProp的值為java.protocol.handler.pkgs if (packagePrefixList != "") { packagePrefixList += "|"; } // REMIND: decide whether to allow the "null" class prefix // or not. packagePrefixList += "sun.net.www.protocol";//拼接默認(rèn)的pkgs StringTokenizer packagePrefixIter = new StringTokenizer(packagePrefixList, "|"); while (handler == null && packagePrefixIter.hasMoreTokens()) {//遍歷pkgs String packagePrefix = packagePrefixIter.nextToken().trim(); try { String clsName = packagePrefix + "." + protocol + ".Handler";//類全名為pkgs.protocal.Handler Class<?> cls = null; try { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { ClassLoader cl = ClassLoader.getSystemClassLoader(); if (cl != null) { cls = cl.loadClass(clsName); } } if (cls != null) { handler = (URLStreamHandler)cls.newInstance(); } } catch (Exception e) { // any number of exceptions can get thrown here } } }

類的命名模式為?[pkgs].[protocol].Handler,比如默認(rèn)實(shí)現(xiàn)”?sun.net.www.protocol.[protocol].Handler”,?比如HTTP?協(xié)議的對(duì)應(yīng)的處理類名為?-sun.net.?www.protocol.http.Handler?

自定義協(xié)議例子如下:

package com.myprotocol.pkgs0.json; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; public class Handler extends URLStreamHandler { @Override protected URLConnection openConnection(URL u) throws IOException { return new URLConnection(u) { public InputStream getInputStream() throws IOException { return new FileInputStream("d:/aaaa.txt"); } @Override public void connect() throws IOException { // 建立連接 } }; } } 啟動(dòng)時(shí)命令:java -Djava.protocol.handler.pkgs=com.myp rotocol.pkgs0 其他參數(shù) 主類

3、構(gòu)造方法URL((URL)null, "json://www.google.com",new URLStreamHandler(){...})

這種方法直接設(shè)置Handler,比較簡(jiǎn)單,不在贅述


代理Proxy

URLStreamHandler?覆蓋openConnection(URL)?openConnection(URL,Proxy)?兩個(gè)方法即可



總結(jié)

以上是生活随笔為你收集整理的对Java的URL类支持的协议进行扩展的方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。