程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java URL自界說公有收集協定

Java URL自界說公有收集協定

編輯:關於JAVA

Java URL自界說公有收集協定。本站提示廣大學習愛好者:(Java URL自界說公有收集協定)文章只能為提供參考,不一定能成為您想要的結果。以下是Java URL自界說公有收集協定正文


——聲明,腦殘人士闊別,本博客的焦點不是if-else+前綴,而是若何經由過程URL協定處置框架界說公有協定

URI與URL的差別

URI (uniform resource identifier)同一資本標記符;URL(uniform resource location )同一資本定位符(或同一資本定位器);URI是一個絕對來講更普遍的概念,URL是URI的一種,是URI定名機制的一個子集,可以說URI是籠統的,而詳細要應用URL來定位資本。URI指向的普通不是物理資本途徑,而是全部體系中的映照後的資本標識符。URL是Internet上用來描寫信息資本的字符串,重要用在各類WWW客戶法式和辦事器法式上。采取URL可以用一種同一的格局來描寫各類信息資本,包含文件、辦事器的地址和目次等。


一.先來序文一段

我們習氣了http

 URL url=new URL(http://www.apptest.com:8080/test/ios.php);

我們也要習氣

固然,我們還要讓URL習氣我們

 "https", "ftp", "mailto", "telnet", "file", "ldap", "gopher", "jdbc", "rmi", "jndi", "jar", "doc", "netdoc", "nfs", "verbatim", "finger", "daytime", "systemresource"
 URL url=new URL("oschina://www.apptest.com:8080/test/ios.php");

假如不習氣,總會湧現以下異常

java.net.MalformedURLException: unknown protocol

在Android閱讀器應用Ajax時也會不支撐沒有界說的過的協定。


二.協定的自界說的懂得

協定:在編程的世界裡,協定自己就是一套Input/ouput束縛規矩,是以,我們確實的協定應當環繞I/O睜開的,所以,這裡的協定可以稱為I/O協定。

協定提議方:request

協定呼應方:response

協定成立的前提是:request和reponse承認統一套協定,並依照協定束縛停止通訊。


三.自界說協定與URL的關系

在java中,自界說協定必定須要用URL嗎?

謎底能否定的。

 現實上,環繞I/O,我們的規矩界說完整有我們自己控制,並沒有說分開URL地球不轉了,Java要撲滅了。

為何應用URL類來自界說協定?

謎底是由於URL是一套成熟的協定通訊處置框架。

這裡說的自界說URL協定,本質上更多的是經由過程已有的規矩停止擴大協定。

四.URL自界說公有協定實戰

我們曉得,自界說協定須要Response 和Request,兩邊須要充懂得對方的協定。這裡為了便利起見,我們應用Http協定辦事器來作為Response。

這裡我們應用了Ngnix辦事器+PHP+FastCGI來構建Reponse,安排代碼以下

1.界說Response

<?php$raw_post_data = file_get_contents('php://input', 'r'); 
echo "-------\$_POST------------------\n<br/>"; 
echo var_dump($_POST) . "\n";
 echo "-------php://input-------------\n<br/>"; 
echo $raw_post_data . "\n<br/>";
 $rs = json_encode($_SERVER);file_put_contents('text.html',$rs);echo '寫入勝利';

2.界說Request

2.1完成URLStreamHandlerFactory工場,重要用來發生協定處置器

public class EchoURLStreamHandlerFactory implements URLStreamHandlerFactory {
public URLStreamHandler createURLStreamHandler(String protocol){
//經由過程這裡的分流處置分歧的schema要求,固然腦殘人士以為這裡才是焦點代碼,URL是一套協定處置框架,假如if-else就是焦點,是否是oracle要開張  
if(protocol.equals("echo") || protocol.equals("oschina"))   { 
   return new EchoURLStreamHandler(); //實例化協定處置Handler  
 }  
return null; }}

2.2完成URLStreamHandler,重要感化是生成協定對應的銜接器

public class EchoURLStreamHandler extends URLStreamHandler {
@Overrideprotected URLConnection openConnection(URL u) throws IOException {
return new EchoURLConnection(u); 
//在這裡我們也能夠停止響應的分流}
}

2.3  完成URLConnection,感化是協定通訊規矩的自界說,這裡我們應用HTTP協定作為通訊規矩,我們這裡仿造http協定要求

(以下才是焦點代碼,這裡借用的http協定,固然你可以用websocket,smtp,ftp各類協定停止交互,而不是腦殘人士讓我認可的 if-else+URL前綴)

public class EchoURLConnection extends URLConnection {
private Socket connection = null;
public final static int DEFAULT_PORT = 80;public EchoURLConnection(URL url) {
super(url);}
public synchronized InputStream getInputStream() throws IOException {
if (!connected) {connect();
}
return connection.getInputStream();
}
public synchronized OutputStream getOutputStream() throws IOException {
if (!connected) {connect();
}
return connection.getOutputStream();
}
public String getContentType() {
return "text/plain";
}public synchronized void connect() throws IOException {
if (!connected) {
int port = url.getPort();
if (port < 0 || port > 65535)port = DEFAULT_PORT;
this.connection = new Socket(url.getHost(), port);
// true表現封閉Socket的緩沖,立刻發送數據..其默許值為false// 
若Socket的底層完成不支撐TCP_NODELAY選項,則會拋出SocketExceptionthis.connection.setTcpNoDelay(true);
// 表現能否許可重用Socket所綁定的當地地址this.connection.setReuseAddress(true);
// 表現吸收數據時的期待超不時間,單元毫秒..其默許值為0,表現會無窮期待,永久不會超時
// 當經由過程Socket的輸出流讀數據時,假如還沒稀有據,就會期待
// 超時後會拋出SocketTimeoutException,且拋出該異常後Socket依然是銜接的,可以測驗考試再次讀數據this.connection.setSoTimeout(30000);
// 表現當履行Socket.close()時,能否立刻封閉底層的Socket
// 這裡設置為當Socket封閉後,底層Socket延遲5秒後再封閉,而5秒後一切未發送完的殘剩數據也會被拋棄
// 默許情形下,履行Socket.close()辦法,該辦法會立刻前往,但底層的Socket現實上其實不立刻封閉
// 它會延遲一段時光,直到發送完一切殘剩的數據,才會真正封閉Socket,斷開銜接
// Tips:當法式經由過程輸入流寫數據時,僅僅表現法式向收集提交了一批數據,由收集擔任保送到吸收方
// Tips:當法式封閉Socket,有能夠這批數據還在收集上傳輸,還未達到吸收方
// Tips:這裡所說的"未發送完的殘剩數據"就是指這類還在收集上傳輸,未被吸收方吸收的數據this.connection.setSoLinger(true, 5);
// 表現發送數據的緩沖區的年夜小this.connection.setSendBufferSize(1024);
// 表現吸收數據的緩沖區的年夜小this.connection.setReceiveBufferSize(1024);
// 表現關於長時光處於余暇狀況(銜接的兩頭沒有相互傳送數據)的Socket,能否要主動把它封閉,true為是
// 其默許值為false,表現TCP不會監督銜接能否有用,不運動的客戶端能夠會永遠存鄙人去,而不會留意到辦事器曾經瓦解this.connection.setKeepAlive(true);
// 表現能否支撐發送一個字節的TCP緊迫數據,socket.sendUrgentData(data)用於發送一個字節的TCP緊迫數據
// 其默許為false,即吸收方收到緊迫數據時不作任何處置,直接將其拋棄..若用戶願望發送緊迫數據,則應設其為true
// 設為true後,吸收方會把收到的緊迫數據與通俗數據放在異樣的隊列中this.connection.setOOBInline(true);
// 該辦法用於設置辦事類型,以下代碼要求高靠得住性和最小延遲傳輸辦事(把0x04與0x10停止位或運算)
// Socket類用4個整數表現辦事類型// 0x02:低本錢(二進制的倒數第二位為1)
// 0x04:高靠得住性(二進制的倒數第三位為1)// 0x08:最高吞吐量(二進制的倒數第四位為1)
// 0x10:最小延遲(二進制的倒數第五位為1)this.connection.setTrafficClass(0x04 | 0x10);
// 該辦法用於設定銜接時光,延遲,帶寬的絕對主要性(該辦法的三個參數表現收集傳輸數據的3項目標)
// connectionTime--該參數表現用起碼時光樹立銜接
// latency---------該參數表現最小延遲
// bandwidth-------該參數表現最高帶寬// 可認為這些參數付與隨意率性整數值,這些整數之間的絕對年夜小就決議了響應參數的絕對主要性/
// 如這裡設置的就是---最高帶寬最主要,其次是最小銜接時光,最初是最小延遲this.connection.setPerformancePreferences(2, 1, 3);this.connected = true;StringBuilder sb = new StringBuilder();sb.append("POST " + url.getPath() + " HTTP/1.1 \r\n");
//if(url.getPort()<0 || url.getPort()>65536){sb.append("Host:").append(url.getHost()).append("\r\n");}else{sb.append("Host:").append(url.getHost()).append(":").append(url.getPort()).append("\r\n");}sb.append("Connection:keep-alive\r\n");sb.append("Date:Fri, 22 Apr 2016 13:17:35 GMT\r\n");sb.append("Vary:Accept-Encoding\r\n");sb.append("Content-Type: application/x-www-form-urlencoded,charset=utf-8\r\n");sb.append("Content-Length: ").append("name=zhangsan&password=123456".getBytes("UTF-8").length).append("\r\n");sb.append("\r\n");this.connection.getOutputStream().write(sb.toString().getBytes("UTF-8"));}}public synchronized void disconnect() throws IOException {if (connected) {this.connection.close();this.connected = false;}}}

在這裡,協定界說曾經完成。

我們測試代碼以下

測驗考試銜接  oschina://localhost:8080/test/ios.php

URL.setURLStreamHandlerFactory(new EchoURLStreamHandlerFactory());
// URLConnection.setContentHandlerFactory(new EchoContentHandlerFactory());
URL url=new URL("oschina://localhost:8080/test/ios.php");
EchoURLConnection connection=(EchoURLConnection)url.openConnection();
connection.setDoOutput(true);connection.setDoInput(true); 
PrintWriter pw = new PrintWriter(new OutputStreamWriter(connection.getOutputStream()));
pw.write("name=zhangsan&password=123456");pw.flush(); 
 InputStream stream = connection.getInputStream();    
 int len = -1;  byte[] buf = new byte[256];  
while((len=stream.read(buf, 0, 256))>-1)  { 
 String line = new String(buf, 0, len);  
if(line.endsWith("\r\n0\r\n\r\n")&&len<256)   {    
     //辦事器前往的是Transfer-chunked編碼,\r\n0\r\n\r\n表現讀取停止了,chunked編碼解析:http://dbscx.iteye.com/blog/830644  line = line.substring(0, line.length()-"\r\n0\r\n\r\n".length()); 
 System.out.println(line);  
break;  
}else{  System.out.println(line); 
  } 
 }  
 pw.close(); 
stream.close();

運轉成果

成果解釋,協定確切界說勝利了


固然,如上數據解析不相符我們的請求,由於是chunked編碼信息,若何解析相符請求有,請移步:

HTTP Chunked數據編碼與解析算法

五.後話,自界說mineType解析器

java中供給了ContentHandlerFactory,用來解析mineType,我們這裡制訂我們本身的解析器,固然,JDK中供給的更豐碩,這裡所做的只是為了相符特別需求

public class EchoContentHandler extends ContentHandler {
public Object getContent(URLConnection connection) throws IOException {
InputStream in = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
return br.readLine();
}
public Object getContent(URLConnection connection, Class[] classes) 
throws IOException {InputStream in = connection.getInputStream();
for (int i = 0; i < classes.length; i++) {
if (classes[i] == InputStream.class)return in;
else if (classes[i] == String.class)return getContent(connection);
}return null;}}

用法很簡略

 URLConnection.setContentHandlerFactory(new EchoContentHandlerFactory());

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved