科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道在无线J2ME设备上实现超文本传输协议

在无线J2ME设备上实现超文本传输协议

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在无线J2ME设备上实现超文本传输协议

作者: cyber3 来源:赛迪网技术社区 2007年10月31日

关键字: 超文本 J2ME

  • 评论
  • 分享微博
  • 分享邮件
随着越来越多手提电话和个人数字助理开始融入到信息高速公路之上,从移动设备上访问Web站点变得越来越重要。Java开创了消费设备中小型的储存容量的先河,它是用于开发手机、传呼机及其他微型设备应用程序的理想语言。 E0SsVHXd  
LVxw#g(|  
  在本文中,我们将学习如何从一个J2ME客户机上向服务器发送一条HTTP GET请求和一条HTTP POST请求。虽然这只是一篇探讨性质的文章,但是我还是假定读者已经熟悉Java,J2ME,以及Java Midlets(MIDP应用程序)的运作机制。我们将使用J2ME的MIDP简表,并利用SUN的J2ME的无线应用程序开发工具包编译、配置和测试我们的应用程序。对于HTTP服务器,任何WWW地址都可以被访问,但是默认时我们将使用一个简单的Java Servlet来返回我们的HTTP请求的细节。 '[g]z]{  
4kRHQH9  
  如何使用J2ME客户机向Web服务器和类似的支持HTTP的服务器发送HTTP请求呢?答案就是使用可在javax.microedition.io程序包中可找到的J2ME的网络类。本文就想具体阐述这个问题。 RLm;]rW[lH  
f_{Vb  
  本文概述∶ Sa=X>Ed8f  
  使用J2ME设计无线网络应用程序 G>hR37]  
  .发送一条超文本GET请求 Kiuf0[{R\  
  .发送一条超文本POST请求 uTiE@~b=  
  .使用J2ME进行无线网络编程 lO> ?s7ZHh  
~WCzablW&  
  Java的网络编程能力是相当健壮的。Java 2标准版( J2SE)在java.io和java.net程序包中定义了100多个接口程序,类和异常。通过这些库实现的功能是很强大的,但是这只适用于传统的计算机系统,这些计算机系统有强大的CPU处理能力,快速的内存和持久的数据储存,但是这些在大多数的无线设备上是不现实的。因此,J2ME定义了这些函数的子集,并提供了一套用于网络和文件访问的固定的程序包--- javax.microedition.io程序包。由于可移动设备种类繁多,这个程序包仅仅定义了一套接口,而为每个可移动设备供应厂商留下了实际的应用程序接口实现。这就在可移植性和设备特定特征的应用中找到了一个最佳的平衡点。 |/1LJ54&  
?ooT5;x B  
  定义在javax.microedition.io类中的抽象网络和文件输入输出框架称为通用连接框架(Generic Connection Framework,简称GCF)。GCF定义了一套有关抽象化的内容来描述不同的通信方法。最高级的抽象被称作连接(Connection),还声明了六个接口(四个是直接的,两个是间接的)。这七个接口就构成了J2ME的CLDC的一部分,CLDC是大多数的能使用Java的无线设备使用的配置。设计这个配置的目的就是为所有的CLDC设备(手提电话,双向传呼机,低档的PDA等等)提供公用的网络和文件输入输出能力。虽然GCF的目的是公用网络和文件输入输出框架,但是生产商并不要求实现GCF中声明的所有的接口。有的厂家可以决定只支持socket连接,而其它的厂家可以选择只支持基于数据报的通信。为了促进跨越类似装置的可移植性,MIDP规范要求所有的MIDP设备实现HttpConnection接口。HttpConnection不是GCF的一部分,但是它是从GCF的一个接口ContentConnection衍生出来的。我们将使用HttpConnection接口构造我们样本应用程序。 ~mY[N) R-  
_5yn+v{  
   ;<[{2:bz  
发送一个HTTP GET请求 [l$Q.v1  
x^i8SXcb63  
2V1US|A  
  这一节将重点解释程序代码,在下一节中我们将只讲述被用来发送HTTP请求并检索由服务器返回的响应通用连接框架接口和HttpConnection接口。创建MIDP用户界面的程序代码见附录。 q-..vsE  
|K).bn=T@2  
  我们先要定义一个方法来放用于发送HTTP GET请求的代码。因为这个方法中的有些操作有潜在的抛出IOException的可能,所以我们将把这样的意外(exception)抛给调用方法。 .O[({'  
Copy code
mlc8A%aS  
public String sendHttpGet( String url ) throws IOException { pSLo'%XQ  
HttpConnection hcon = null; :D!RmVs&lv  
DataInputStream dis = null; Z"=u`pR5.  
StringBuffer message = ""; t>-4J(d  
try { 8Q[kR{sc  
+*%=p K  
<L.wHTA  
  第一步是使用Connector类打开一个到服务器的连接,这是GCF的关键。我们将把这个连接强制转换为需要的类型,在本例中为HttpConnection类型。 l]7to7xPs  
TD+umjdlr  
hcon = ( HttpConnection ) Connector.open( url ); Ie;9> n  
:,JfRL{  
35PYjz+Np  
  接下来,我们得到HttpConnection上的一个DataInputStream,允许我们一个字符一个字符的读取服务器的响应数据。 v8K~o{ $u  
0k._>7*[  
dis = new DataInputStream( hcon.openInputStream() ); wEu]At2D  
/5H0Ze  
  使用DataInputStream的read ()方法,服务器响应的每个字符都被集中起来放入StringBuffer对象。 Su[,&>{4S7  
Copy code
^2 IUg@[r  
int ch; M!bzm6tz0  
while ( ( ch = dis.read() ) != -1 ) { 8l3X5w)  
message = message.append( ( char ) ch ); xCl9d<S(M  
} ~%Ba^ >  
QHbd@_  
-G-r-|[~  
  最后,连接对象被净空以保存资源,而信息从这个方法中返回。 OGy(5B~  
Copy code
p{J 4 [o  
} finally { l<1Qym3 F  
if ( hcon != null ) hcon.close(); s:n D}+1  
if ( dis != null ) dis.close(); oJhB11\  
}//结束try/finally代码段 *6.#E`.w  
return message.toString(); ~a2z-xq*E  
}//结束 sendGetRequest( String ) [>O^K|  
C)yL_n  
   d\ 7guJq1  
如何发送一个HTTP POST请求 m$VBDLU'  
bN *@ {  
r[#NyM xU  
  你可以想象,发送一个HTTP POST请求的处理过程其实与发送一个GET请求非常地类似。我们将修改一个现有命令,添加少量的新的命令,并添加一个来自通用连接框架的附加的对象和一个附加的StringBuffer对象把POST请求体重的内容发送到服务器中。剩下的命令将保持不变。 Vm^)y$xKp:  
@yOD%D >H  
  复制我们刚才创建的sendHttpGet()方法,把它粘贴进同一个类文件,改名为sendHttpPost()。 现在,我们将修改这个新方法来发送一个HTTP POST请求到服务器。 在方法的顶部添加两个新的变量说明。 声明一个类型为DataOutputStream的变量和另一个String类型的变量。 我们将使用DataOutputStream对象把存在于字符串变量中的POST请求体发送到服务器中。 ^m+ftdU  
L)gO' -  
DataOutputStream dos = null; {DUgssih  
String requestBody = null; clJRr#(  
^]$b|O.k  
  修改connector.open()命令包含另一个参数,指出连接将允许客户端可以通过连接在服务器上读和写。 sz'm@U5  
2Hd4mWw0  
hcon = ( HttpConnection ) Connector.open( url, Connector.READ_WRITE ); %FPk^D-p*  
>?gaVim  
  设置HttpConnection对象使用的请求方法为POST(默认的方法是GET)。 grHAZZn  
K=Bi5h! :  
hcon.setRequestMethod( HttpConnection.POST ); w vbI&k e  
d|+-'2"7s?  
  得到一个用于现有的HTTP连接的DataOutputStream对象。 T>,Pz3  
(Sn-B/+`  
dos = hc.openDataOutputStream(); oM~!Fe[+  
R&E(tS`54V  
  声明一个字节数组并通过检索一个来自requestBody字符串的字节数组初始化。 然后把DataOutputStream的缓冲写入字节数组内。 meZ6/}!  
Copy code
%%f:kV  
byte[] byteRequest = requestBody.getBytes(); [.O8.yWh  
for( int i = 0; i < byteRequest.length; i++ ) { -N.QJ?[,W{  
dos.writeByte(byteRequest[i]); _SiVZwzP  
} //结束for( int i = 0; i < byteRequest.length; i++ ) 8 3x-L  
dos.flush(); //包含本句,在某些设被上将可能会产生不可预期的结果  ijd1dj  
$(gyc/TS-  
  调用flush ()方法的意图是发送已经写入的数据到DataOutputStream的服务器的缓冲区中。 在某些电话上,这个操作工作正常,在其他的电话上,它导致HTTP请求的Transfer - Encoding被设置为" chunked ",有一些随机字符被放到请求本身的前面和后面。那又怎样处理这个问题呢?这个方法调用实际上是根本不需要的。在接下来的一行中,服务器连接打开(通过openInputStream ()),将自动输入缓冲区。因此,你最好不要调用缓冲区的flush()方法。这个方法其余的部分保持不变,除了DataOutputStream对象必须在finally{}语句块中关闭。 ega:A?NR  
k e5; 5 ]  
Copy code
d@ObS1"MB  
} finally { ^/)yj)@E  
if ( hc != null ) hc.close(); ~ ]\ K  
+=qLA2i  
if ( dis != null ) dis.close(); 3cQ%$x@  
7,Y:HaqnO1  
if ( dos != null ) dis.close(); `[yTA@'_)[  
}//结束 try/finally "n}  z  
U)^#L+f l  
<1tvfG  
  这就是所有的程序代码!并请参见本文后附带的程序代码。 EHj8[e^ZG  
o+M D`/  
  随着可以使用国际互联网络和支持网络的无线设备日益的增多普及,Java和J2ME的重要性也在不断的变大。因为HTTP协议是当前仅有的,被所有的遵从MIDP规范的设备支持的网络协议,它也是用于开发无线网络应用程序的最好的候选者。 Vwu##;~  
IUM[;V  
  在本文中,我们探究了无线网络编程的基本结构和几个核心问题,我们看了如何调用两个最常用的HTTP请求方法:GET和POST。J2ME仍然在它的发展初期,并且无线设备也即将得到大面积的普及。所以,所有有志投身于无线网络编程中的开发者们将得到大展拳脚的好机会。 uFp/Op`U^0  
@d[K.-]{  
附录: 64HcSi{~  
TQ=GG}BS@  
Copy code
bD|5B0A'  
/* Z:?$lbXvib  
* HttpMidlet.java xnMF: N  
*/ k!G(TT3t  
import javax.microedition.midlet.*; Qa '~h(  
import javax.microedition.lcdui.*; 8 T; ~bQ  
import javax.microedition.io.*; j>Z@xx@  
import java.io.*; Q/~= }PB  
GT7"RNa/   
]YH>j1G)5S  
public class HttpMidlet extends MIDlet implements CommandListener { ~ ~R{X{t  
//使用默认的URL。用户可以从图形用户接口改变这个值 W#gZx%dWN  
private static String defaultURL = "[url]http://localhost:8080/test/servlet/EchoServlet[/url]"; X,,I:n9  
g|^v>eZU  
// 主MIDP 显示 @-'GQ^#$  
private Display myDisplay = null; RA@KD>a  
k0p^O zTr}  
// 输入URL的图形用户接口组件 nPxR(FiJ+  
private Form requestScreen;  % *?$  
private TextField requestField; O 'ZDra  
H 6 /{mH  
// 用于提交请求的图形用户接口组件 G%kg'1 zE  
private List list; *;sBjMsBh  
private String[] menuItems; - H*A@#K9,  
yLO^o<CV  
// 用于显示服务器响应的图形用户接口组件 @*obb*j  
private Form resultScreen; {0Zu  
private StringItem resultField; uk "U  
Aob!6  
//用于requestScreen的"send"按钮 PwOU{RH A  
Command sendCommand; sgXu+$:<:  
// 用于requestScreen的"exit"按钮 _U.Oe*90oh  
Command exitCommand; Mh~JWD|)  
// 用于requestScreen的"back"按钮 wQ$5BV 6G  
Command backCommand; 7n+(w  
s]w/IYE(  
public HttpMidlet(){ 1>E6qK&*  
// 初始化图形用户接口组件 a&Ni  
myDisplay = Display.getDisplay( this ); }u/B0s(  
sendCommand = new Command( "SEND", Command.OK, 1 ); &8]!|Z  
exitCommand = new Command( "EXIT", Command.OK, 1 ); Dm\-a)Tus  
backCommand = new Command( "BACK", Command.OK, 1 ); 4EcD]A o.  
N[pZ-yux  
//显示请求的URL -B+k}aU$L  
requestScreen = new Form( "Type in a URL:" ); Sg(V7  
requestField = new TextField( null, defaultURL, 100, TextField.URL ); Gk)"w?5w  
requestScreen.append( requestField ); }3?wg  
requestScreen.addCommand( sendCommand ); 2vNv6_%  
requestScreen.addCommand( exitCommand ); SJB0|z   
requestScreen.setCommandListener( this ); e 0 0Mg  
m /W$i  
// 选择想要的HTTP请求方法 h/ khw}~  
menuItems = new String[] {"GET Request", "POST Request"}; 7=UnB[  
list = new List( "Select an HTTP method:", List.IMPLICIT, menuItems, null ); qQ%0fcLxJ  
list.setCommandListener( this ); ez=\2  
1vT*O<  
// 先是从服务器上收到的信息 .:'S%q }  
resultScreen = new Form( "Server Response:" ); +*Zc4w  
resultScreen.addCommand( backCommand ); )6DBiy  
resultScreen.setCommandListener( this ); r_[- l5O  
av|ablH  
}//结束HttpMidlet() *dt::'c  
;%RCU&e|#  
public void startApp() { <fcw)5' V  
myDisplay.setCurrent( requestScreen ); cJyPa/8sf  
}//结束 startApp() v2`o-H  
9UU?&[PV  
public void commandAction( Command com, Displayable disp ) { 4*=9!YR  
// 当用户点击"send"按钮 .X!_T%q  
if ( com == sendCommand ) { yWOgrR>ju#  
myDisplay.setCurrent( list ); \Z,lQ@q-  
} else if ( com == backCommand ) { G8v`,JRbY  
requestField.setString( defaultURL ); ;J1)6_c  
myDisplay.setCurrent( requestScreen ); E ~"D {  
} else if ( com == exitCommand ) { j3E`X4_@w:  
destroyApp( true ); q|H[\$R  
notifyDestroyed(); ^F,'q  
}//结束 if ( com == sendCommand ) )Zcj)g]7  
wjHo:)R>Mh  
if ( disp == list && com == List.SELECT_COMMAND ) { Bk \Qe?  
[q0YpnWn  
String result; AZv*$CXI  
>Ir?#kxG)  
if ( list.getSelectedIndex() == 0 ) // 发送一个 GET 请求到服务器 nJne |'b  
result = sendHttpGet( requestField.getString() ); /]su~s`  
else // 发送一个 POST 请求到服务器 C$ )Ul-~V  
result = sendHttpPost( requestField.getString() ); yS`4s(8SP  
Is^ }:~{2  
resultField = new StringItem( null, result ); e2\^ ?L&#q  
resultScreen.append( resultField ); vlzSN( +  
myDisplay.setCurrent( resultScreen ); Du>3SXFun  
}//结束if ( dis == list && com == List.SELECT_COMMAND ) v)cJ `AzY  
}//结束 commandAction( Command, Displayable ) )3%78E}1  
`lyp.5u  
private String sendHttpGet( String url ) n*H5t/;  
{ @#[a W  
HttpConnection hcon = null; FUmi (2  
DataInputStream dis = null; m"/n+S ,5  
StringBuffer responseMessage = new StringBuffer(); CzSGCCoQ  
gCzkCc~)}  
try { (nee@oOg  
//使用READ权限的标准的 HttpConnection /BgUS ]Y:  
hcon = ( HttpConnection )Connector.open( url ); 2SZ'N7dV  
Es;3avbAS  
//从HttpConnection取得一个 DataInputStream Q!}RjZnd  
dis = new DataInputStream( hcon.openInputStream() ); kXf Y  
A/ W-ao  
// 从服务器上取回响应 vn<RV  
int ch; >7oyWBmP  
while ( ( ch = dis.read() ) != -1 ) { ^0iVY[q>  
responseMessage.append( (char) ch ); w /W+{<:  
}//结束while ( ( ch = dis.read() ) != -1 ) Y:*i:83 r  
} VJ *ktE  
catch( Exception e ) vZo~g_ ]  
{ E ZZy;  
e.printStackTrace(); ?qK&.t  
responseMessage.append( "ERROR" ); ]XDOu!|  
} finally { KoL0?5Da5+  
try { ]pw^nw e  
if ( hcon != null ) hcon.close(); ; 5 t &  
if ( dis != null ) dis.close(); ) ( #HU  
} catch ( IOException ioe ) { !~~j2g_ O  
ioe.printStackTrace(); %dVl;P.  
}//结束try/catch K!U<>GtQ}  
}//结束try/catch/finally aZYwvy^i  
return responseMessage.toString(); H[9!8w@  
}//结束sendHttpGet( String ) qmBJ&4:H3  
MCmy0 BD  
private String sendHttpPost( String url ) "s&o/UBD  
{ vlR W  
HttpConnection hcon = null; xp~>zh*X+#  
DataInputStream dis = null; <zBt}P S  
DataOutputStream dos = null; .j2"?,GC`  
StringBuffer responseMessage = new StringBuffer(); ~$xgZ(z2  
// 请求体 3V]Aq4j  
String requeststring = "This is a POST.";  !2"hY  
~OZX)5+4A4  
try { v<g Q{\r%  
// 使用读写权限的 HttpConnection qOE1*LGw  
hcon = ( HttpConnection )Connector.open( url, Connector.READ_WRITE ); {Qru9xL  
[.1v VL2  
//设置请求方法为POST =.=yx#;  
hcon.setRequestMethod( HttpConnection.POST ); %bQ:M|^1  
P= =5>S(  
// 取得发送请求字符串的DataOutputStream ,ob-^Qz  
dos = hcon.openDataOutputStream(); R en_  
byte[] request_body = requeststring.getBytes(); 0qfV.  
:b9K _Uc-  
// 发送请求字符串到服务器 Yl4BL,$9>  
for( int i = 0; i < request_body.length; i++ ) { ^ S =Y#  
dos.writeByte( request_body[i] ); 9I St[N*  
}//结束 for( int i = 0; i < request_body.length; i++ ) JM RYDVt  
o.Mi0  
// 取得做为接收服务器响应的DataInputStream 7PiCm(  
dis = new DataInputStream( hcon.openInputStream() ); 3uoM5Hl0xX  
<DM"Im+Vm8  
// 从服务器上取回响应 <J,S |`  
int ch; e,,)([  
while( ( ch = dis.read() ) != -1 ) { Q5KcaL  
responseMessage.append( (char)ch ); T1M4"XU  
}//结束while( ( ch = dis.read() ) != -1 ) { r~$2/HkB  
} !)UMwCqd  
catch( Exception e ) &X!A@   
{ iKT<H<H  
e.printStackTrace(); ]r*Pc .$x  
responseMessage.append( "ERROR" ); ;x  
} lR"67R  
finally { i$GBOrZ(  
// 释放输入输出流和HTTP连接 "'OWCK e  
try { Ycbs !K?  
if( hcon != null ) hcon.close(); rmw*Bu|F  
if( dis != null ) dis.close(); Hfz||[%UG  
if( dos != null ) dos.close(); bs)A#EFI45  
} catch ( IOException ioe ) { Oz;D`XW  
ioe.printStackTrace(); ]xm3BXp  
}//结束try/catch (<I.M>  
}//结束try/catch/finally Y>--*1L1  
return responseMessage.toString(); c ']+ JX{  
}//结束sendHttpPost( String ) FrSsSkg  
9Kj0azz8o  
public void pauseApp() { n]Mf0em  
}//结束pauseApp() ^bn?[TE6  
4*.Nb0^  
public void destroyApp( boolean unconditional ) { reL{28F  
myDisplay = null; yTdBlZ  
requestScreen = null; ])EOeOPE  
requestField = null; OUx=`Yh05  
resultScreen = null; AJ9-er  
resultField = null; CK0v.3G  
}//结束 destroyApp( boolean ) Lr>d3W 9  
}//结束HttpMidlet ktq?EwtS!  
查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章