用无线设备比如手机上网的时候经常需要通过表单提交一些数据,比如登录操作,通常的情况下服务器端我们采用CGI后者Servlet来执行这些操作。
CLDC作为受限设备的基本配置通常会提供通用的连接框架给开发者连进行网络开发。另外MIDP还提供HttpConnection的接口,这个接口是javax.microedition.io的一部分,这里面定义了最基本的HTTP连接需要的方法和常量。
本文主要大概介绍一下HTTP的POST和GET操作,以及如何运用他们并举例说明如何通过MIDlets的POST和GET操作激活一个CGI和Servlets。本文还将包含在无线环境下用于追踪会话的不同技术。
HTTP编程的原理
HTTP协议是一个请求-相应的应用协议,协议规定请求发出前各个参数必须事先设置。比如当用户点击表单的提交按钮后表单内填入的内容会作为请求的一部分发送给服务器端。
请求的方法类型
目前有两种方法可以用来向服务器端提交请求:GET和POST。这两种方法决定数据如何递交给服务器。
采用GET方式要递交的值作为URL的一部分发送给服务器端,其递交的值将成为环境变量QUERY_STRING。
采用POST方式递交的值作为一个输入流发送给服务器端,其流的长度会放在CONTENT_LENGTH里。
相对两种方法POST方法更安全一些,通过POST方法也可以传输多种数据。
利用GET方式递交信息的例子
如下是一个用GET方式递交表单的HTML例子:
action="http://www.somesite.com/cgi-bin/getgrade.cgi"
method="GET"
Student#:
表单提交给http://www.somesite.com/cgi-bin/getgrade.cgi,当用户输入一个学号比如123333,点击Retrieve Marks按钮后表单的数据将作为URL的一部分发送给CGI程序。递交的地址为http://www.somesite.com/cgi-bin/gergrade.cgi?idnum=123333。用POST方式递交数据时输入的数值将作为分段的输入流发送给服务器。
GET方式用户输入中带有空格时这些空格将被(+)取代,当用户一次要递交多个数值时这些数值用(&)分割。
Servlet编程原理
和CGI相似,Servlets支持请求、响应的编程方式,当一个客户端发送一个请求给服务器,服务器将这个请求发送给servlet。servlet组织一个响应发回给客户端。跟CGI不同的是servlet对多次请求使用一个进程处理。
当客户端递交了一个请求,servlet 的 service方法就被调用并将请求传递给request和response。首先servlet判断请求是post还是get方式,并决定用HttpServlet.doGet还是HttpServlet.doPost方法来处理这个请求。这两个方法都将调用HttpServletRequest和HttpServletResponse。
通过MIDlet激活CGI脚本
了解了基本的HTTP GET,POST和servlets之后,让我们来看一个例子。第一个例子是用来说明如何用MIDlet通过POST方式激活一个CGI脚本。
例子中当打开了pgrade.cgi这个CGI的连接后跟着打开可输出和输入流。输入的内容通过output流发送。得到的响应通过input流获得。CGI脚本是用PERL写的,脚本中获得学号后在数据库中查找此学号的记录,如果找到就返回相关的信息给请求的客户端。因为在MIDlet里并没有表单可用于提交,所以内容要通过写流的方法实现。下面是MIDlet的代码。
PostMidlet.java
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* An example MIDlet to invoke a CGI script
* using the POST method.
**/
public class PostMidlet extends MIDlet {
private Display display;
String url = "http://somesite.com/cgi-bin/pgrade.cgi";
public PostMidlet() {
display = Display.getDisplay(this);
}
//Initialization. Invoked the MIDlet activates.
public void startApp() {
try {
getGrade(url);
} catch (IOException e) {
System.out.println("IOException " + e);
e.printStackTrace();
}
}
//Pause, discontinue ....
public void pauseApp() { }
//Destroy must cleanup everything.
public void destroyApp(boolean unconditional) { }
//Retrieve a grade.
void getGrade(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
OutputStream os = null;
StringBuffer b = new StringBuffer();
TextBox t = null;
try {
c = (HttpConnection)Connector.open(url);
c.setRequestMethod(HttpConnection.POST);
c.setRequestProperty("IF-Modified-Since", "20 Jan 2001 16:19:14 GMT");
c.setRequestProperty("User-Agent", "Profile/MIDP-1.0 Configuration/CLDC-1.0");
c.setRequestProperty("Content-Language", "en-CA");
os = c.openOutputStream();
// send request to the CGI script
String str = "name=163748";
byte postmsg[] = str.getBytes();
for(int i=0;
os.write(postmsg[i]);
}
os.flush();
//receive response and display in a text box.
is = c.openDataInputStream();
int ch;
while((ch = is.read()) != -1) {
b.append((char) ch);
System.out.println((char)ch);
}
t = new TextBox("Final Grades", b.toString(), 1024, 0);
} finally {
if(is!= null) {
is.close();
}
if(os != null) {
os.close();
}
if(c != null) {
c.close();
}
}
display.setCurrent(t);
}
}
当你运行PostMidlet后你将看到如下的画面
用MIDlet激活Servlet
你可以象MIDlet激活一个CGI一样激活servlet,本段将介绍两个例子:
第一个例子用GET操作激活一个Servlet,并显示结果。
第二个例子是servlet接受用户由手机POST上来的数据
激活一个Servlet
下面这个例子的内容是,FirstMidletServlet被GET方法激活并返回显示给手机。本例中并没有递交数据给Servlet, Servlet被激活后一会返回字符串“Servlet Invoked”和日期给客户端。
下面是MIDlet的代码
FirstMidletServlet.java
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* An example MIDlet to invoke a CGI script.
*/
public class FirstMidletServlet extends MIDlet {
private Display display;
String url = "http://somesite.com/servlet/HelloServlet";
public FirstMidletServlet() {
display = Display.getDisplay(this);
}
//Initialization. Invoked when MIDlet activates
public void startApp() {
try {
invokeServlet(url);
} catch (IOException e) {
System.out.println("IOException " + e);
e.printStackTrace();
}
}
//Pause, discontinue ....
public void pauseApp() { }
//Destroy must cleanup everything.
public void destroyApp(boolean unconditional) { }
//Prepare connection and streams then invoke servlet.
void invokeServlet(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
StringBuffer b = new StringBuffer();
TextBox t = null;
try {
c = (HttpConnection)Connector.open(url);
c.setRequestMethod(HttpConnection.GET);
c.setRequestProperty("IF-Modified-Since", "20 Jan 2001 16:19:14 GMT");
c.setRequestProperty("User-Agent", "Profile/MIDP-1.0 Configuration/CLDC-1.0");
c.setRequestProperty("Content-Language", "en-CA");
is = c.openDataInputStream();
int ch;
// receive response and display it in a textbox.
while ((ch = is.read()) != -1) {
b.append((char) ch);
}
t = new TextBox("First Servlet", b.toString(), 1024, 0);
} finally {
if(is!= null) {
is.close();
}
if(c != null) {
c.close();
}
}
display.setCurrent(t);
}
}
下面是返回“Servlet Invoked”和日期的HelloServlet代码
HelloServlet.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* The simplest possible servlet.
*/
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request