1. AccountInfo.java

/**//*
* 与服务器共享的序列化信息
* 序列化用户的基本信息
*/
package com.chapter16.shared;

import java.io.*;


public class AccountInfo ...{
private String userName = "";//登陆的用户名

private String password = "";//登陆密码

private String creditCardNumber = "";//银行卡号

private String creditCardHolderName = "";//银行卡用户名

private String creditCardExpirationDate = "";//银行卡截止日期


public AccountInfo() ...{
}


public void setUserName(String userName) ...{
this.userName = userName;
}


public String getUserName() ...{
return userName;
}


public String getPassword() ...{
return password;
}


public void setPassword(String password) ...{
this.password = password;
}


public String getCreditCardNumber() ...{
return creditCardNumber;
}


public void setCreditCardNumber(String creditCardNumber) ...{
this.creditCardNumber = creditCardNumber;
}


public String getCreditCardHolderName() ...{
return creditCardHolderName;
}


public void setCreditCardHolderName(String creditCardHolderName) ...{
this.creditCardHolderName = creditCardHolderName;
}


public String getCreditCardExpirationDate() ...{
return creditCardExpirationDate;
}


public void setCreditCardExpirationDate(String creditCardExpirationDate) ...{
this.creditCardExpirationDate = creditCardExpirationDate;
}

public byte[] serialize() throws IOException ...{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dataStream = new DataOutputStream(bout);
dataStream.writeUTF(userName);
dataStream.writeUTF(password);
dataStream.writeUTF(creditCardNumber);
dataStream.writeUTF(creditCardHolderName);
dataStream.writeUTF(creditCardExpirationDate);
return bout.toByteArray();
}


public void deserialize(byte[] data) throws IOException ...{
ByteArrayInputStream bin = new ByteArrayInputStream(data);
DataInputStream dataStream = new DataInputStream(bin);
userName = dataStream.readUTF();
password = dataStream.readUTF();
creditCardNumber = dataStream.readUTF();
creditCardHolderName = dataStream.readUTF();
creditCardExpirationDate = dataStream.readUTF();
}

}


2. BillInfo.java

/**//*
* 序列化缴费清单的基本信息
*/
package com.chapter16.shared;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;



public class BillInfo ...{
private String billdate = "";//缴费日期

private String money = "";//缴费金额

private String reason = "";//缴费说明



public String getBilldate() ...{
return billdate;
}

public void setBilldate(String billdate) ...{
this.billdate = billdate;
}


public String getReason() ...{
return reason;
}


public void setReason(String reason) ...{
this.reason = reason;
}

public String getMoney() ...{
return money;
}

public byte[] serialize() throws IOException ...{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dataStream = new DataOutputStream(bout);
dataStream.writeUTF(billdate);
dataStream.writeUTF(money);
dataStream.writeUTF(reason);
return bout.toByteArray();
}


public void deserialize(byte[] data) throws IOException ...{
ByteArrayInputStream bin = new ByteArrayInputStream(data);
DataInputStream dataStream = new DataInputStream(bin);
billdate = dataStream.readUTF();
money = dataStream.readUTF();
reason = dataStream.readUTF();
}

public void setMoney(String money) ...{
this.money = money;
}
}

3. MessageConstants.java
//消息常量的类,是服务器端程序和客户端程序同时使用的消息类
package com.chapter16.shared;


public final class MessageConstants ...{
public static final byte OPERATION_LOGIN_USER = 0;
public static final byte OPERATION_LIST_ACCOUNT = 1;
public static final byte OPERATION_UPDATE_ACCOUNT = 2;

public static final byte ERROR_NONE = 0;
public static final byte ERROR_UNKNOWN_OPERATION = 1;
public static final byte ERROR_SERVER_ERROR = 2;
public static final byte ERROR_MODEL_EXCEPTION = 3;
public static final byte ERROR_REQUEST_FORMAT = 4;


private MessageConstants() ...{}

}
4. ProgressObserver.java
//实现一个进度条接口
package com.chapter16.bankbillClent;


public interface ProgressObserver ...{
public boolean isStoppable();
public void setStoppable(boolean stoppable);
public boolean isStopped();
public void updateProgress();
public void setNote(String note);
}
5. ProgressObserverUI.java
//进度条屏幕类
package com.chapter16.bankbillClent;

import javax.microedition.lcdui.*;



public class ProgressObserverUI extends Form implements ProgressObserver,

CommandListener ...{
private static final int GAUGE_MAX = 8;
private static final int GAUGE_LEVELS = 4;
int current = 0;
Gauge gauge;
Command stopCommand;
boolean stoppable;
boolean stopped;


public ProgressObserverUI() ...{
super("");

gauge = new Gauge("", false, GAUGE_MAX, 0);
stopCommand = new Command("停止",
Command.STOP, 10);

append(gauge);
setCommandListener(this);
}


public void init(String note, boolean stoppable) ...{
gauge.setValue(0);
setNote(note);
setStoppable(stoppable);

stopped = false;
}


public void setNote(String note) ...{
setTitle(note);
}


public boolean isStoppable() ...{
return stoppable;
}


public void setStoppable(boolean stoppable) ...{
this.stoppable = stoppable;


if (stoppable) ...{
addCommand(stopCommand);

} else ...{
removeCommand(stopCommand);
}
}


public boolean isStopped() ...{
return stopped;
}


public void updateProgress() ...{
current = (current + 1) % GAUGE_LEVELS;

gauge.setValue(current * GAUGE_MAX / GAUGE_LEVELS);
}


public void commandAction(Command c, Displayable d) ...{

if (c == stopCommand) ...{
stopped = true;
}
}

}
6. HTTPCommunication.java
//负责提供所有客户端屏幕显示所需要的数据
package com.chapter16.bankbillClent;

import javax.microedition.io.*;
import javax.microedition.lcdui.*;

import com.chapter16.shared.BillInfo;
import com.chapter16.shared.MessageConstants;
import com.chapter16.shared.AccountInfo;
import java.io.*;


public class HTTPCommunication ...{
private String serviceURL;

private boolean offline = true;

private ProgressObserverUI progressObserverUI = null;

public HTTPCommunication(String serviceURL,

ProgressObserverUI progressObserverUI) ...{

this.serviceURL = serviceURL;
this.progressObserverUI = progressObserverUI;

return;
}


public boolean isOffline() ...{
return offline;
}


public void setOffline(boolean offline) ...{
this.offline = offline;

return;
}


public boolean login(String userName, String password) ...{
int passed = 0;
HttpConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;


try ...{
connection = openConnection();

updateProgress();

outputStream = openConnectionOutputStream(connection);

outputStream.writeByte(MessageConstants.OPERATION_LOGIN_USER);
outputStream.writeUTF(userName);
outputStream.writeUTF(password);
outputStream.close();
updateProgress();

inputStream = openConnectionInputStream(connection);
passed = inputStream.readInt();
System.out.println(passed);
updateProgress();
//如果服务器返回1,则表示登陆成功


} catch (IOException ioe) ...{

} finally ...{
//释放资源
closeConnection(connection, outputStream, inputStream);
}
if (passed == 1)
return true;
else
return false;
}


public BillInfo[] getBillData() throws IOException ...{

HttpConnection conn = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;


try ...{
conn = openConnection();
//更新进度条
updateProgress();
outputStream = openConnectionOutputStream(conn);

outputStream.writeByte(MessageConstants.OPERATION_LIST_ACCOUNT);


if (conn.getResponseCode() == HttpConnection.HTTP_OK) ...{

inputStream = openConnectionInputStream(conn);
//更新进度条
updateProgress();

//获得缴费信息
int length = (int) conn.getLength();

if (length > 0) ...{
//读取传输过来的缴费清单的数目
int num = inputStream.readInt();
BillInfo[] binfo = new BillInfo[num];

for (int i = 0; i < num; i++) ...{
byte[] data = new byte[inputStream.readInt()];
//读取数据
inputStream.read(data);
binfo[i] = new BillInfo();
binfo[i].deserialize(data);
//显示返回信息
}
//更新进度条
updateProgress();
return binfo;

}
}


} catch (Exception e) ...{
System.out.println(e.toString());

} finally ...{
//释放资源

if (progressObserverUI != null) ...{
progressObserverUI = null;
}
closeConnection(conn, outputStream, inputStream);
}
return null;
}


public boolean updateAccount(AccountInfo accountInfo) ...{
int passed = 0;
HttpConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;


try ...{
connection = openConnection();

//更新进度条
updateProgress();

outputStream = openConnectionOutputStream(connection);
//发送更新信息的消息
outputStream.writeByte(MessageConstants.OPERATION_UPDATE_ACCOUNT);

//发送用户信息
byte[] data = accountInfo.serialize();
//发送数据的长度
outputStream.writeInt(data.length);
//发送数据
outputStream.write(data);

outputStream.close();
updateProgress();
//从服务器上获得是否成功发送的结果
inputStream = openConnectionInputStream(connection);
passed = inputStream.readInt();
//更新进度条
updateProgress();

} catch (IOException ioe) ...{

} finally ...{
closeConnection(connection, outputStream, inputStream);
}
if (passed == 1)
return true;
else
return false;
}


private HttpConnection openConnection() throws IOException ...{

try ...{
HttpConnection connection = (HttpConnection) Connector
.open(serviceURL);

connection.setRequestProperty("User-Agent",
"BANKBILL1.0/MIDP-2.0 Configuration/CLDC-1.1");
connection.setRequestProperty("Content-Type",
"application/octet-stream");
connection.setRequestMethod(HttpConnection.POST);

offline = false;

return connection;

} catch (IOException ioe) ...{
offline = true;

throw ioe;
}
}

private DataOutputStream openConnectionOutputStream(

HttpConnection connection) throws IOException ...{

try ...{
return connection.openDataOutputStream();

} catch (IOException ioe) ...{
offline = true;

throw ioe;
}
}

private DataInputStream openConnectionInputStream(HttpConnection connection)

throws IOException ...{

try ...{
int responseCode = connection.getResponseCode();


if (responseCode == HttpConnection.HTTP_OK) ...{
DataInputStream inputStream = connection.openDataInputStream();
return inputStream;
}


} catch (IOException ioe) ...{
offline = true;
}
return null;
}

void closeConnection(HttpConnection connection,

DataOutputStream outputStream, DataInputStream inputStream) ...{

if (outputStream != null) ...{

try ...{
outputStream.close();

} catch (IOException ioe) ...{
}
}


if (inputStream != null) ...{

try ...{
inputStream.close();

} catch (IOException ioe) ...{
}
}


if (connection != null) ...{

try ...{
connection.close();

} catch (IOException ioe) ...{
}
}

return;
}


protected void updateProgress() ...{

if (progressObserverUI != null) ...{

if (!progressObserverUI.isStopped()) ...{
progressObserverUI.updateProgress();
return;
}
}
}
}


7. SignOnUI.java
//登陆屏幕类
package com.chapter16.bankbillClent;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

import com.chapter16.shared.BillInfo;


public class SignOnUI extends Form implements CommandListener ...{

private TextField userNameField;

private TextField passwordField;

private Command signOnCommand;
private Command backCommand;

private MIDlet midlet;
private Display display;
private Displayable parent;

private ProgressObserverUI progressObserverUI;


public SignOnUI(MIDlet midlet,Displayable parent) ...{
super("登陆");

userNameField = new TextField("用户名:", null, 12, TextField.ANY);
passwordField = new TextField("密码:", null, 20, TextField.PASSWORD);
signOnCommand = new Command("登陆", Command.OK, 5);
backCommand = new Command("返回", Command.BACK, 5);
this.midlet = midlet;
this.display = Display.getDisplay(midlet);
this.parent = parent;
progressObserverUI = new ProgressObserverUI();
append("请输入你的用户名和密码");
append(userNameField);
append(passwordField);
addCommand(signOnCommand);
addCommand(backCommand);
setCommandListener(this);
}


public void init() ...{

userNameField.setString(null);
passwordField.setString(null);
}


public void commandAction(Command command, Displayable displayable) ...{

if(command == signOnCommand)...{
signOn(userNameField.getString(), passwordField.getString());
}

if(command == backCommand)...{
display.setCurrent(parent);
}
}


public void signOn(final String userName, final String password) ...{

Thread thread = new Thread() ...{

public void run() ...{

try ...{
System.out.println("处理用户登陆");
//model.login(userName, password);
BankBillListUI bbui=null;
String url = "http://127.0.0.1:8080/TEst/BankBillServlet";
HTTPCommunication hc = new HTTPCommunication(url,progressObserverUI);
//显示帐单情况

if(hc.login(userName,password) == true)...{
BillInfo[] binfo = hc.getBillData();
bbui = new BankBillListUI(midlet,parent,binfo);
display.setCurrent(bbui);

}else...{
showErrorAlert("登陆不成功,请重新输入用户名和密码!",SignOnUI.this);
}
//成功登陆则切换到查询和缴费模块
//关闭progressObserverUI对象
if(progressObserverUI != null)
progressObserverUI = null;

} catch (Exception e) ...{
showErrorAlert(e.getMessage(), display.getCurrent());
}
}

};

runWithProgress(thread, "正在登陆", false);
}


public void runWithProgress(Thread thread, String title, boolean stoppable) ...{
progressObserverUI.init(title, stoppable);
display.setCurrent(progressObserverUI);
thread.start();
}


private void showErrorAlert(String message, Displayable d) ...{
Alert alert = new Alert("错误");

alert.setType(AlertType.ERROR);
alert.setTimeout(Alert.FOREVER);
alert.setString(message);
display.setCurrent(alert, d);
}

}
8. BankBillListUI.java
//查询屏幕类
package com.chapter16.bankbillClent;

import java.io.*;

import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

import com.chapter16.shared.BillInfo;



public class BankBillListUI extends Form implements CommandListener ...{
private Display display;
private Displayable parent;
private BillInfo[] binfo;
private Command backCommand;

public BankBillListUI(MIDlet midlet,Displayable parent,BillInfo[] binfo) ...{
super("缴费清单");
backCommand = new Command("返回", Command.BACK, 5);
this.display = Display.getDisplay(midlet);
this.parent = parent;
this.binfo = binfo;

if(binfo != null)...{

for(int i = 0; i< binfo.length;i++)...{
this.append("第 "+ (i+1) +" 条信息:");
this.append(binfo[i].getBilldate());
this.append(binfo[i].getMoney());
this.append(binfo[i].getReason());
}
}
this.addCommand(backCommand);
this.setCommandListener(this);
}


public void commandAction(Command c, Displayable d) ...{

if(c == backCommand)...{
display.setCurrent(parent);
}
}

}
9. AccountInfoUI.java
//帐户信息屏幕类
package com.chapter16.bankbillClent;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

import com.chapter16.shared.AccountInfo;




public class AccountInfoUI extends Form implements CommandListener ...{

private TextField userNameField;
private TextField passwordField;
private TextField cardHolderNameField;
private TextField cardNumberField;


private Command sendCommand;
private Command backCommand;

private MIDlet midlet;
private Display display;
private Displayable parent;

private ProgressObserverUI progressObserverUI;


public AccountInfoUI(MIDlet midlet,Displayable parent) ...{
super("登陆");

userNameField = new TextField("用户名:", null, 12, TextField.ANY);
passwordField = new TextField("密码:", null, 20, TextField.PASSWORD);
cardHolderNameField = new TextField("信用卡拥有人:", null, 12, TextField.ANY);
cardNumberField = new TextField("卡号:", null, 30, TextField.NUMERIC);
sendCommand = new Command("发送", Command.OK, 5);
backCommand = new Command("返回", Command.BACK, 5);
this.midlet = midlet;
this.display = Display.getDisplay(midlet);
this.parent = parent;
progressObserverUI = new ProgressObserverUI();
append("请输入你的用户名和密码");
append(userNameField);
append(passwordField);
append(cardHolderNameField);
append(cardNumberField);
addCommand(sendCommand);
addCommand(backCommand);
setCommandListener(this);
}


public void init() ...{

userNameField.setString(null);
passwordField.setString(null);
}


public void commandAction(Command command, Displayable displayable) ...{

if(command == sendCommand)...{
sendInfo(userNameField.getString(), passwordField.getString());
}

if(command == backCommand)...{
display.setCurrent(parent);
}
}


public void sendInfo(final String userName, final String password) ...{

Thread thread = new Thread() ...{

public void run() ...{

try ...{
System.out.println("处理用户登陆");
//model.login(userName, password);
BankBillListUI bbui=null;
String url = "http://127.0.0.1:8080/TEst/BankBillServlet";
HTTPCommunication hc = new HTTPCommunication(url,progressObserverUI);
//发送用户信息
AccountInfo accinfo = new AccountInfo();
accinfo.setUserName(userNameField.getString());
accinfo.setPassword(passwordField.getString());
accinfo.setCreditCardNumber(cardNumberField.getString());
accinfo.setCreditCardHolderName(cardHolderNameField.getString());

if(hc.updateAccount(accinfo)==false)...{
showErrorAlert("发送不成功,请重新发送信息!",AccountInfoUI.this);

}else...{
showErrorAlert("发送成功,将返回主屏幕!",AccountInfoUI.this);
}
//关闭progressObserverUI对象
if(progressObserverUI != null)
progressObserverUI = null;

} catch (Exception e) ...{
showErrorAlert(e.getMessage(), display.getCurrent());
}
}

};

runWithProgress(thread, "正在登陆", false);
}


public void runWithProgress(Thread thread, String title, boolean stoppable) ...{
progressObserverUI.init(title, stoppable);
display.setCurrent(progressObserverUI);
thread.start();
}


private void showErrorAlert(String message, Displayable d) ...{
Alert alert = new Alert("错误");

alert.setType(AlertType.ERROR);
alert.setTimeout(Alert.FOREVER);
alert.setString(message);
display.setCurrent(alert, d);
}

}
10. BankBillMidlet.java

/**//*
* 缴费系统主程序
*/
package com.chapter16.bankbillClent;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;


public class BankBillMidlet extends MIDlet implements CommandListener ...{
private Command exitCommand, commitCommand;

private List mainList;

Display display;


public BankBillMidlet() ...{
exitCommand = new Command("Exit", Command.EXIT, 1);
commitCommand = new Command("选择", Command.SCREEN, 1);
Image[] imageArray = null;

try ...{
Image icon = Image.createImage("/remote.png");
// 设置列表所需要的图像数组

imageArray = new Image[] ...{
icon,
icon,
icon
};

} catch (java.io.IOException err) ...{
// ignore the image loading failure the application can recover.
System.out.print("load failed ...");
imageArray = null;
}

String[] stringArray = ...{
"登陆",
"设置帐户信息",
"缴费"
};
mainList = new List("移动银行缴费系统", Choice.IMPLICIT, stringArray,
imageArray);

mainList.addCommand(exitCommand);
mainList.addCommand(commitCommand);
//设置命令监听对象
mainList.setCommandListener(this);

display = Display.getDisplay(this);

}


protected void startApp() throws MIDletStateChangeException ...{
display.setCurrent(mainList);
}


protected void pauseApp() ...{
}


protected void destroyApp(boolean p1) ...{
}


public void commandAction(Command c, Displayable d) ...{

if (c == exitCommand) ...{
destroyApp(false);
notifyDestroyed();

} else if (c == commitCommand) ...{

if (d.equals(mainList)) ...{

switch (((List)d).getSelectedIndex()) ...{
case 0:
SignOnUI signForm = new SignOnUI(this,mainList);
display.setCurrent(signForm);
break;

case 1:
AccountInfoUI accinfoUI = new AccountInfoUI(this,mainList);
display.setCurrent(accinfoUI);
break;
case 2:
break;

}
}
}

}
}
11. BankBillServlet.java
//服务器端的Servlet
package com.chapter16.bankbill;

import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.DataSource;

import com.chapter16.shared.*;


public class BankBillServlet extends HttpServlet ...{

protected static final String DBName = "java:/DefaultDS";

private DataSource dataSource;

public void init(ServletConfig config) throws ServletException ...{


try ...{
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup(DBName);

} catch (Exception e) ...{
e.printStackTrace();
throw new ServletException("init error");
}

}

protected void doGet(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException ...{

}

protected void doPost(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException ...{
response.setContentType("application/octet-stream");
InputStream is = request.getInputStream();
OutputStream os = response.getOutputStream();
DataInputStream call = new DataInputStream(is);
DataOutputStream result = new DataOutputStream(os);

//分清楚需要处理的模块
byte method = call.readByte();

switch (method) ...{
//处理登录模块
case MessageConstants.OPERATION_LOGIN_USER:
login(call,result);

break;
//显示欠费列表
case MessageConstants.OPERATION_LIST_ACCOUNT:
sendBillInfo(request,response);
break;
case MessageConstants.OPERATION_UPDATE_ACCOUNT:
updateAccount(call,result);
break;
}
response.setContentLength(result.size());

}
private void updateAccount(DataInputStream call,

DataOutputStream result) throws IOException ...{
byte[] data = new byte[call.readInt()];
call.read(data);
AccountInfo accinfo = new AccountInfo();
accinfo.deserialize(data);
System.out.println(accinfo.getUserName());
System.out.println(accinfo.getPassword());
System.out.println(accinfo.getCreditCardHolderName());
System.out.println(accinfo.getCreditCardNumber());

//进行数据库验证是否用户名和密码合法
//这里省略了数据库的验证部分,直接返回一个合法的信息
//如果成功登录返回1
result.writeInt(1);
return;
}

private void login(DataInputStream call,

DataOutputStream result) throws IOException...{
String username = call.readUTF();
String password = call.readUTF();
System.out.println(username);
System.out.println(password);
//进行数据库验证是否用户名和密码合法
//这里省略了数据库的验证部分,直接返回一个合法的信息
//如果成功登录返回1
result.writeInt(1);
return;
}
private void sendBillInfo(HttpServletRequest request,

HttpServletResponse response) throws IOException...{
Connection conn;
response.setContentType("application/octet-stream");
OutputStream os = response.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);

try ...{
conn = dataSource.getConnection();
//获得行数
PreparedStatement ps1 = conn.prepareStatement("SELECT COUNT(*) As rowcount"
+ " FROM BANKBILL");
ResultSet rs1 = ps1.executeQuery();
rs1.next();
int num = rs1.getInt("rowcount");
rs1.close();
ps1.close();
PreparedStatement ps = conn.prepareStatement("SELECT *"
+ " FROM BANKBILL");
ResultSet rs = ps.executeQuery();
//发送账单数目
dos.writeInt(num);
BillInfo binfo = new BillInfo();

while (rs.next()) ...{
binfo.setBilldate(rs.getString(1));
binfo.setMoney(rs.getString(2));
binfo.setReason(rs.getString(3));
byte[] data = binfo.serialize();
//一条记录的长度
dos.writeInt(data.length);
//发送账单数据
dos.write(data);
System.out.println(rs.getString(1));
}

rs.close();
ps.close();
conn.close();

} catch (SQLException e) ...{

e.printStackTrace();
}
response.setContentLength(dos.size());
dos.close();
os.close();
}
}