在CLDC中並沒有對序列化機制進行支持,但是這並不影響我們在J2ME聯網或者RMS操作中使用這種有效的機制,本文將講述如何采用序列化機制進行J2ME聯網。
如果讀者對TOMCAT的使用和Java IO還不熟悉那麼請參考如下兩篇文章,作為本文的准備。Java的基本數據類型與流,Tomcat入門指南。我們要編寫一個用戶注冊的應用程序,用戶填寫自己的信息然後通過聯網把數據發送到服務器,在Server端我們用Servlet來接收用戶的數據。這樣有一個好處就是當我們需要修改用戶注冊的選項的時候,比如添加一個選項,我們不需要修改程序的聯網部分,只需要修改用戶類的序列化和反序列化方法就可以了。下面看看我們的Account類,它是對用戶的注冊信息進行封裝,並提供了兩個重要的方法serialize()和deserialize()。
package com.J2MEdev.mingJava;
import Java.io.*;
public class Account
{
private String userName = "";
private String email = "";
private int age = 0;
private boolean gender = false;
public Account()
{
}
public Account(String userName, String email, int age, boolean gender)
{
this.userName = userName;
this.email = email;
this.age = age;
this.gender = gender;
}
public void serialize(DataOutputStream DOS) throws IOException
{
DOS.writeUTF(userName);
DOS.writeUTF(email);
DOS.writeInt(age);
DOS.writeBoolean(gender);
}
public static Account deserialize(DataInputStream dis) throws IOException
{
Account account = new Account();
account.userName = dis.readUTF();
account.email = dis.readUTF();
account.age = dis.readInt();
account.gender = dis.readBoolean();
return account;
}
public String toString()
{
return "UserName = " + userName + " Email = " + email + " age = " + age
+ " gender = " + (gender ? "male" : "female");
}
}
當我們進行聯網操作的時候,只需要調用account.serialize(DOS),例如
private void connect(String url)
{
HttpConnection httpConn = null;
DataOutputStream DOS = null;
InputStream is = null;
try
{
System.out.println("connecting to server.....");
httpConn = (HttpConnection) Connector.open(url);
httpConn.setRequestMethod(HttpConnection.POST);
DOS = new DataOutputStream(httpConn.openOutputStream());
System.out.println(account.toString());
account.serialize(DOS);
DOS.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
服務器端收到客戶端傳送過來的Stream後,處理起來更簡單,調用Account.deserialize(dis)就可以得到account對象了。
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
int length = request.getContentLength();
System.out.println(length);
DataInputStream dis = new DataInputStream(request.getInputStream());
Account myAccount = Account.deserialize(dis);
System.out.println(myAccount.toString());
}
我們下面做個簡單的MIDlet,目的是收集用戶填寫的注冊信息然後發送給服務器。界面如下所示:
代碼如下所示:
package com.J2MEdev.mingJava;
import Javax.microedition.lcdui.Choice;
import Javax.microedition.lcdui.ChoiceGroup;
import Javax.microedition.lcdui.Command;
import Javax.microedition.lcdui.CommandListener;
import Javax.microedition.lcdui.Display;
import Javax.microedition.lcdui.Displayable;
import Javax.microedition.lcdui.Form;
import Javax.microedition.lcdui.TextFIEld;
import Javax.microedition.midlet.MIDlet;
import Javax.microedition.midlet.MIDletStateChangeException;
import Java.io.*;
import Javax.microedition.io.*;
public class NetworkMIDlet extends MIDlet implements CommandListener
{
private Display display;
private Form mainForm;
private TextFIEld userName;
private TextFIEld email;
private TextFIEld age;
private ChoiceGroup gender;
private NetworkThread nt;
public static final Command connectCommand = new Command("Connect",
Command.ITEM, 2);
public static final Command exitCommand = new Command("Exit", Command.EXIT,
1);
public static final String URL = "http://localhost:8088/net/myservlet";
protected void startApp() throws MIDletStateChangeException
{
initMIDlet();
}
private void initMIDlet()
{
display = Display.getDisplay(this);
mainForm = new Form("個人信息");
userName = new TextField("姓名",null,20,TextFIEld.ANY);
email = new TextField("電子信箱",null,25,TextFIEld.EMAILADDR);
age = new TextField("年齡",null,20,TextFIEld.ANY);
gender = new ChoiceGroup("性別",Choice.EXCLUSIVE);
gender.append("男",null);
gender.append("女",null);
mainForm.append(userName);
mainForm.append(email);
mainForm.append(age);
mainForm.append(gender);
mainForm.addCommand(connectCommand);
mainForm.addCommand(exitCommand);
mainForm.setCommandListener(this);
display.setCurrent(mainForm);
nt = new NetworkThread(this);
nt.start();
}
private void exitMIDlet()
{
try
{
destroyApp(false);
notifyDestroyed();
} catch (MIDletStateChangeException e)
{
e.printStackTrace();
}
}
protected void pauseApp()
{
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
}
public void commandAction(Command arg0, Displayable arg1)
{
if(arg0 == connectCommand)
{
String name = userName.getString();
String mail = email.getString();
int myAge = Integer.parseInt(age.getString());
int i = gender.getSelectedIndex();
boolean myGender = i==0?true:false;
Account account = new Account(name,mail,myAge,myGender);
nt.setAccount(account);
// System.out.println(account.toString());
synchronized(this)
{
notify();
}
}
else if(arg0 == exitCommand)
{
exitMIDlet();
}
}
class NetworkThread extends Thread
{
private NetworkMIDlet midlet;
private boolean going = true;
private Account account = null;
public NetworkThread(NetworkMIDlet midlet)
{
this.midlet = midlet;
}
public synchronized void setAccount(Account account)
{
this.account = account;
}
public void run()
{
while (going)
{
synchronized (midlet)
{
try
{
midlet.wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
connect(URL);
}
}
private void connect(String url)
{
HttpConnection httpConn = null;
DataOutputStream DOS = null;
InputStream is = null;
try
{
System.out.println("connecting to server.....");
httpConn = (HttpConnection) Connector.open(url);
httpConn.setRequestMethod(HttpConnection.POST);
DOS = new DataOutputStream(httpConn.openOutputStream());
System.out.println(account.toString());
account.serialize(DOS);
DOS.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
服務器端我們只是把從客戶端發送過來的數據反序列化後打印到控制台。Servlet的代碼如下所示:
import Java.io.DataInputStream;
import Java.io.IOException;
import Javax.servlet.ServletException;
import Javax.servlet.http.HttpServlet;
import Javax.servlet.http.HttpServletRequest;
import Javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet
{
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
doPost(request,response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
int length = request.getContentLength();
System.out.println(length);
DataInputStream dis = new DataInputStream(request.getInputStream());
Account myAccount = Account.deserialize(dis);
System.out.println(myAccount.toString());
}
}
一定要把Account類也放到Server端,這樣才可以實現反序列化的。(注意clIEnt和server的package並不一定)。啟動Tomcat服務器,當客戶端向服務器發送數據後,我們就可以在服務器端看到了。