`
soardragon
  • 浏览: 316413 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

在无线J2ME设备上实现HTTP协议

阅读更多

随着越来越多手提电话和个人数字助理开始融入到信息高速公路之上,从移动设备上访问Web站点变得越来越重要。Java开创了消费设备中小型的储存容量的先河,它是用于开发手机、传呼机及其他微型设备应用程序的理想语言。
  在本文中,我们将学习如何从一个J2ME客户机上向服务器发送一条HTTPGET请求和一条HTTPPOST请求。虽然这只是一篇探讨性质的文章,但是我还是假定读者已经熟悉Java,J2ME,以及JavaMidlets(MIDP应用程序)的运作机制。我们将使用J2ME的MIDP简表,并利用SUN的J2ME的无线应用程序开发工具包编译、配置和测试我们的应用程序。对于HTTP服务器,任何WWW地址都可以被访问,但是默认时我们将使用一个简单的JavaServlet来返回我们的HTTP请求的细节。

  如何使用J2ME客户机向Web服务器和类似的支持HTTP的服务器发送HTTP请求呢?答案就是使用可在javax.microedition.io程序包中可找到的J2ME的网络类。本文就想具体阐述这个问题。

  本文概述∶
  使用J2ME设计无线网络应用程序
  .发送一条超文本GET请求
  .发送一条超文本POST请求
  .使用J2ME进行无线网络编程

  Java的网络编程能力是相当健壮的。Java2标准版(J2SE)在java.io和java.net程序包中定义了100多个接口程序,类和异常。通过这些库实现的功能是很强大的,但是这只适用于传统的计算机系统,这些计算机系统有强大的CPU处理能力,快速的内存和持久的数据储存,但是这些在大多数的无线设备上是不现实的。因此,J2ME定义了这些函数的子集,并提供了一套用于网络和文件访问的固定的程序包---javax.microedition.io程序包。由于可移动设备种类繁多,这个程序包仅仅定义了一套接口,而为每个可移动设备供应厂商留下了实际的应用程序接口实现。这就在可移植性和设备特定特征的应用中找到了一个最佳的平衡点。

  定义在javax.microedition.io类中的抽象网络和文件输入输出框架称为通用连接框架(GenericConnectionFramework,简称GCF)。GCF定义了一套有关抽象化的内容来描述不同的通信方法。最高级的抽象被称作连接(Connection),还声明了六个接口(四个是直接的,两个是间接的)。这七个接口就构成了J2ME的CLDC的一部分,CLDC是大多数的能使用Java的无线设备使用的配置。设计这个配置的目的就是为所有的CLDC设备(手提电话,双向传呼机,低档的PDA等等)提供公用的网络和文件输入输出能力。虽然GCF的目的是公用网络和文件输入输出框架,但是生产商并不要求实现GCF中声明的所有的接口。有的厂家可以决定只支持socket连接,而其它的厂家可以选择只支持基于数据报的通信。为了促进跨越类似装置的可移植性,MIDP规范要求所有的MIDP设备实现HttpConnection接口。HttpConnection不是GCF的一部分,但是它是从GCF的一个接口ContentConnection衍生出来的。我们将使用HttpConnection接口构造我们样本应用程序。

发送一个HTTPGET请求

  这一节将重点解释程序代码,在下一节中我们将只讲述被用来发送HTTP请求并检索由服务器返回的响应通用连接框架接口和HttpConnection接口。创建MIDP用户界面的程序代码见附录。

  我们先要定义一个方法来放用于发送HTTPGET请求的代码。因为这个方法中的有些操作有潜在的抛出IOException的可能,所以我们将把这样的意外(exception)抛给调用方法。

publicStringsendHttpGet(Stringurl)throwsIOException{;
HttpConnectionhcon=null;
DataInputStreamdis=null;
StringBuffermessage="";
try{;

  第一步是使用Connector类打开一个到服务器的连接,这是GCF的关键。我们将把这个连接强制转换为需要的类型,在本例中为HttpConnection类型。

hcon=(HttpConnection)Connector.open(url);

  接下来,我们得到HttpConnection上的一个DataInputStream,允许我们一个字符一个字符的读取服务器的响应数据。

dis=newDataInputStream(hcon.openInputStream());

  使用DataInputStream的read()方法,服务器响应的每个字符都被集中起来放入StringBuffer对象。

intch;
while((ch=dis.read())!=-1){;
message=message.append((char)ch);
};

  最后,连接对象被净空以保存资源,而信息从这个方法中返回。

};finally{;
if(hcon!=null)hcon.close();
if(dis!=null)dis.close();
};//结束try/finally代码段
returnmessage.toString();
};//结束sendGetRequest(String)

  如何发送一个HTTPPOST请求

  你可以想象,发送一个HTTPPOST请求的处理过程其实与发送一个GET请求非常地类似。我们将修改一个现有命令,添加少量的新的命令,并添加一个来自通用连接框架的附加的对象和一个附加的StringBuffer对象把POST请求体重的内容发送到服务器中。剩下的命令将保持不变。

  复制我们刚才创建的sendHttpGet()方法,把它粘贴进同一个类文件,改名为sendHttpPost()。现在,我们将修改这个新方法来发送一个HTTPPOST请求到服务器。在方法的顶部添加两个新的变量说明。声明一个类型为DataOutputStream的变量和另一个String类型的变量。我们将使用DataOutputStream对象把存在于字符串变量中的POST请求体发送到服务器中。

DataOutputStreamdos=null;
StringrequestBody=null;

  修改connector.open()命令包含另一个参数,指出连接将允许客户端可以通过连接在服务器上读和写。

hcon=(HttpConnection)Connector.open(url,Connector.READ_WRITE);

  设置HttpConnection对象使用的请求方法为POST(默认的方法是GET)。

hcon.setRequestMethod(HttpConnection.POST);

  得到一个用于现有的HTTP连接的DataOutputStream对象。

dos=hc.openDataOutputStream();

  声明一个字节数组并通过检索一个来自requestBody字符串的字节数组初始化。然后把DataOutputStream的缓冲写入字节数组内。

byte[]byteRequest=requestBody.getBytes();
for(inti=0;i<byteRequest.length;i++){;
dos.writeByte(byteRequest[i]);
};//结束for(inti=0;i<byteRequest.length;i++)

dos.flush();//包含本句,在某些设被上将可能会产生不可预期的结果

  调用flush()方法的意图是发送已经写入的数据到DataOutputStream的服务器的缓冲区中。在某些电话上,这个操作工作正常,在其他的电话上,它导致HTTP请求的Transfer-Encoding被设置为"chunked",有一些随机字符被放到请求本身的前面和后面。那又怎样处理这个问题呢?这个方法调用实际上是根本不需要的。在接下来的一行中,服务器连接打开(通过openInputStream()),将自动输入缓冲区。因此,你最好不要调用缓冲区的flush()方法。这个方法其余的部分保持不变,除了DataOutputStream对象必须在finally{;};语句块中关闭。

};finally{;
if(hc!=null)hc.close();

if(dis!=null)dis.close();

if(dos!=null)dis.close();
};//结束try/finally


  这就是所有的程序代码!并请参见本文后附带的程序代码。

  随着可以使用国际互联网络和支持网络的无线设备日益的增多普及,Java和J2ME的重要性也在不断的变大。因为HTTP协议是当前仅有的,被所有的遵从MIDP规范的设备支持的网络协议,它也是用于开发无线网络应用程序的最好的候选者。

  在本文中,我们探究了无线网络编程的基本结构和几个核心问题,我们看了如何调用两个最常用的HTTP请求方法:GET和POST。J2ME仍然在它的发展初期,并且无线设备也即将得到大面积的普及。所以,所有有志投身于无线网络编程中的开发者们将得到大展拳脚的好机会。

  附录:

/*
*HttpMidlet.java
*/
importjavax.microedition.midlet.*;
importjavax.microedition.lcdui.*;
importjavax.microedition.io.*;
importjava.io.*;

publicclassHttpMidletextendsMIDletimplementsCommandListener{;
//使用默认的URL。用户可以从图形用户接口改变这个值
privatestaticStringdefaultURL="http://localhost:8080/test/servlet/EchoServlet";;

//主MIDP显示
privateDisplaymyDisplay=null;

//输入URL的图形用户接口组件
privateformrequestScreen;
privateTextFieldrequestField;

//用于提交请求的图形用户接口组件
privateListlist;
privateString[]menuItems;

//用于显示服务器响应的图形用户接口组件
privateformresultScreen;
privateStringItemresultField;

//用于requestScreen的"send"按钮
CommandsendCommand;
//用于requestScreen的"exit"按钮
CommandexitCommand;
//用于requestScreen的"back"按钮
CommandbackCommand;

publicHttpMidlet(){;
//初始化图形用户接口组件
myDisplay=Display.getDisplay(this);
sendCommand=newCommand("SEND",Command.OK,1);
exitCommand=newCommand("EXIT",Command.OK,1);
backCommand=newCommand("BACK",Command.OK,1);

//显示请求的URL
requestScreen=newform("TypeinaURL:");
requestField=newTextField(null,defaultURL,100,TextField.URL);
requestScreen.append(requestField);
requestScreen.addCommand(sendCommand);
requestScreen.addCommand(exitCommand);
requestScreen.setCommandListener(this);

//选择想要的HTTP请求方法
menuItems=newString[]{;"GETRequest","POSTRequest"};;
list=newList("SelectanHTTPmethod:",List.IMPLICIT,menuItems,null);
list.setCommandListener(this);

//先是从服务器上收到的信息
resultScreen=newform("ServerResponse:");
resultScreen.addCommand(backCommand);
resultScreen.setCommandListener(this);

};//结束HttpMidlet()

publicvoidstartApp(){;
myDisplay.setCurrent(requestScreen);
};//结束startApp()

publicvoidcommandAction(Commandcom,Displayabledisp){;
//当用户点击"send"按钮
if(com==sendCommand){;
myDisplay.setCurrent(list);
};elseif(com==backCommand){;
requestField.setString(defaultURL);
myDisplay.setCurrent(requestScreen);
};elseif(com==exitCommand){;
destroyApp(true);
notifyDestroyed();
};//结束if(com==sendCommand)

if(disp==list&&com==List.SELECT_COMMAND){;

Stringresult;

if(list.getSelectedIndex()==0)//发送一个GET请求到服务器
result=sendHttpGet(requestField.getString());
else//发送一个POST请求到服务器
result=sendHttpPost(requestField.getString());

resultField=newStringItem(null,result);
resultScreen.append(resultField);
myDisplay.setCurrent(resultScreen);
};//结束if(dis==list&&com==List.SELECT_COMMAND)
};//结束commandAction(Command,Displayable)

privateStringsendHttpGet(Stringurl)
{;
HttpConnectionhcon=null;
DataInputStreamdis=null;
StringBufferresponseMessage=newStringBuffer();

try{;
//使用READ权限的标准的HttpConnection
hcon=(HttpConnection)Connector.open(url);

//从HttpConnection取得一个DataInputStream
dis=newDataInputStream(hcon.openInputStream());

//从服务器上取回响应
intch;
while((ch=dis.read())!=-1){;
responseMessage.append((char)ch);
};//结束while((ch=dis.read())!=-1)
};
catch(Exceptione)
{;
e.printStackTrace();
responseMessage.append("ERROR");
};finally{;
try{;
if(hcon!=null)hcon.close();
if(dis!=null)dis.close();
};catch(IOExceptionioe){;
ioe.printStackTrace();
};//结束try/catch
};//结束try/catch/finally
returnresponseMessage.toString();
};//结束sendHttpGet(String)

privateStringsendHttpPost(Stringurl)
{;
HttpConnectionhcon=null;
DataInputStreamdis=null;
DataOutputStreamdos=null;
StringBufferresponseMessage=newStringBuffer();
//请求体
Stringrequeststring="ThisisaPOST.";

try{;
//使用读写权限的HttpConnection
hcon=(HttpConnection)Connector.open(url,Connector.READ_WRITE);

//设置请求方法为POST
hcon.setRequestMethod(HttpConnection.POST);

//取得发送请求字符串的DataOutputStream
dos=hcon.openDataOutputStream();
byte[]request_body=requeststring.getBytes();

//发送请求字符串到服务器
for(inti=0;i<request_body.length;i++){;
dos.writeByte(request_body[i]);
};//结束for(inti=0;i<request_body.length;i++)

//取得做为接收服务器响应的DataInputStream
dis=newDataInputStream(hcon.openInputStream());

//从服务器上取回响应
intch;
while((ch=dis.read())!=-1){;
responseMessage.append((char)ch);
};//结束while((ch=dis.read())!=-1){;
};
catch(Exceptione)
{;
e.printStackTrace();
responseMessage.append("ERROR");
};
finally{;
//释放输入输出流和HTTP连接
try{;
if(hcon!=null)hcon.close();
if(dis!=null)dis.close();
if(dos!=null)dos.close();
};catch(IOExceptionioe){;
ioe.printStackTrace();
};//结束try/catch
};//结束try/catch/finally
returnresponseMessage.toString();
};//结束sendHttpPost(String)

publicvoidpauseApp(){;
};//结束pauseApp()

publicvoiddestroyApp(booleanunconditional){;
myDisplay=null;
requestScreen=null;
requestField=null;
resultScreen=null;
resultField=null;
};//结束destroyApp(boolean)
};//结束HttpMidlet

分享到:
评论

相关推荐

    在无线J2ME设备上实现http传输.doc

    在无线J2ME设备上实现HTTP传输涉及到的关键技术主要包括Java Micro Edition (J2ME)、MIDP(Mobile Information Device Profile)、HTTP协议以及J2ME的网络编程接口。J2ME是Java平台的一个轻量级版本,专为资源有限的...

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

    在无线J2ME设备上实现超文本传输协议主要涉及到的是如何使用Java Micro Edition (J2ME)技术在有限资源的移动设备上与Web服务器进行通信。J2ME是一种轻量级的Java平台,专为嵌入式设备如手机、PDA等设计,它包括了...

    精通J2ME无线编程.pdf

    读者将学习到如何编写、编译和测试J2ME应用程序,以及如何在模拟器和真实设备上运行这些程序。 在核心概念部分,作者会介绍CLDC和MIDP的关键组件,如Class Library、User Interface (UI) 构建、以及如何使用Java ...

    J2ME 无线设备编程

    **J2ME 无线设备编程**是Java技术在移动设备和嵌入式系统中的应用,主要针对资源有限的设备如手机、智能手表等。J2ME全称为Java Micro Edition,它是Java平台的一个子集,旨在为小型设备提供可移植性和性能优化的...

    J2ME无线设备编程

    **J2ME无线设备编程**,全称Java 2 Micro Edition,是Java平台的一个子集,主要用于嵌入式系统和移动设备,特别是针对无线通信设备的编程。它为开发手机应用、游戏、智能设备等提供了强大的工具和支持。J2ME在2000...

    J2ME无线设备编程指南

    在“J2ME无线设备编程指南”中,我们将深入探讨如何利用J2ME技术开发无线应用,为这些设备提供丰富的功能。 1. **J2ME架构** J2ME由配置(Configurations)和框架(Profiles)组成。配置定义了最小的Java运行环境...

    J2ME无线设备程序设计-.rar

    WAT,全称为Wireless Application Toolkit,是Sun Microsystems(现已被Oracle收购)推出的一款模拟器,用于测试J2ME应用在不同无线设备上的行为。它可以帮助开发者在没有物理设备的情况下进行开发和调试,模拟各种...

    在J2ME中开发蓝牙无线软件

    特别是针对蓝牙无线技术的支持,J2ME提供了一个强大的框架——Java APIs for Bluetooth wireless technology (JABWT),这使得开发者能够轻松地在各种移动设备上开发蓝牙应用。 #### 二、Java蓝牙API概述 Java蓝牙...

    J2ME MIDP 无线设备编程指南

    **J2ME MIDP 无线设备编程指南** Java 2 Micro Edition (J2ME) 是一个专门为嵌入式和移动设备设计的 Java 平台,它使得开发者能够为各种小型设备,如手机、个人数字助手(PDA)以及无线设备编写应用程序。MIDP...

    J2ME MIDP无线设备编程指南

    Java 2 Micro Edition (J2ME) 是一个专为嵌入式和移动设备设计的Java平台,它允许开发者创建能够在各种小型设备上运行的应用程序,如手机、智能手表和家用电器。MIDP(Mobile Information Device Profile)是J2ME的...

    J2ME 无线音乐随身听

    "J2ME 无线音乐随身听"是一款利用J2ME技术打造的音乐播放软件,旨在为用户在移动设备上提供便捷的音乐体验。 首先,本地播放功能允许用户在他们的设备上播放已存储的音频文件。这通常涉及到对MP3、WAV等常见音频...

    J2ME网络编程以及网络游戏的实现

    J2ME的出现使得跨平台的软件开发成为可能,特别是对于那些需要在不同设备间共享应用程序的移动无线设备。它的核心优势在于Java语言的平台无关性,这使得开发者可以编写一次代码,到处运行。 在网络通信领域,J2ME...

    Wireless Programming With J2ME J2ME 无线网络编程

    J2ME是Java平台的一个子集,主要用于开发和部署在移动设备、嵌入式系统以及物联网设备上的应用程序。 **描述解读:**这本书被誉为经典之作,意味着它深入探讨了如何利用J2ME进行无线网络编程,涵盖了从基本概念到...

    j2me无线应用学习源码.rar

    虽然J2ME主要用于移动设备,但有时需要与服务器端的J2EE应用进行数据交换,例如,通过HTTP协议进行远程方法调用(RMI)或者使用Java Message Service(JMS)进行消息传递。这部分源码可能会展示如何在J2ME应用中集成...

    J2ME无线通信技术应用开发

    在J2ME中,无线通信技术的应用开发是核心领域之一,它使得设备能够通过无线网络进行数据交换,实现各种丰富的功能和服务。 **1. J2ME架构与配置** J2ME由多个配置(Configurations)和Profile(Profiles)组成。...

    j2ME手机移动开发

    j2ME支持通过无线通信协议栈进行数据交换,如HTTP和TCP/IP。这使得开发者可以创建能够访问互联网资源的应用,如天气预报查询、新闻阅读器等。 ### 7. 资源管理与优化 由于移动设备的资源有限,j2ME开发者必须关注...

    简单的蓝牙通讯代码通过j2me 的蓝牙设备可以实现多个蓝牙手机之间的设备通讯

    J2ME是Java的一种轻量级版本,常用于移动设备,如早期的智能手机,它提供了在这些设备上开发应用程序的框架。 描述中提到的“bexDemo,不错的例子”,暗示我们有一个名为bexDemo的示例应用,该应用展示了如何利用...

    J2ME MIDP 2.0 无线设备编程的一些源码

    MIDP(Mobile Information Device Profile)是J2ME中的一个重要配置,它为开发无线设备上的应用程序提供了API。MIDP 2.0是MIDP的一个升级版本,增加了许多新功能和改进,以提高用户体验和开发者便利性。 **一、MIDP...

Global site tag (gtag.js) - Google Analytics