J2ME 裝置無法直接連接資料庫 (無 JDBC 驅動、防火牆限制、資安考量)。標準架構採用 中介層 Servlet:J2ME 發送 HTTP 請求 → Servlet 接收、呼叫 JDBC → 回傳資料 (文字/JSON/XML)。本文以 Tomcat 5.5 + JDK 1.6 + ODBC 資料源為例,完整示範從伺服器端部署到用戶端呼叫的全流程。
JAVA_HOME=C:\jdk1.6CATALINA_HOME=C:\Tomcat5.5PATH=%JAVA_HOME%\bin;%CATALINA_HOME%\bin;...CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\lib\servlet-api.jarmydata6D1,資料表 users(id char(4), name varchar(20))sa,密碼: 空白目錄結構:
Tomcat5.5/webapps/6D1/
├── WEB-INF/
│ ├── web.xml
│ └── classes/
│ └── returnMsg.class
import java.sql.*;
import javax.sql.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class returnMsg extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html; charset=gb2312");
ServletOutputStream out = res.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeUTF("這是測試結果");
dos.writeUTF("下面是數據信息");
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:mydata", "sa", "");
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM users");
while (rs.next()) {
dos.writeUTF("\n用戶ID: " + rs.getString("id"));
dos.writeUTF("\n用戶名: " + rs.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { if (rs != null) rs.close(); } catch (Exception ignore) {}
try { if (stmt != null) stmt.close(); } catch (Exception ignore) {}
try { if (conn != null) conn.close(); } catch (Exception ignore) {}
}
}
}
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="https://java.sun.com/xml/ns/j2ee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/j2ee
https://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>returnMsg</servlet-name>
<servlet-class>returnMsg</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>returnMsg</servlet-name>
<url-pattern>/returnMsg</url-pattern>
</servlet-mapping>
</web-app>
編譯:javac -classpath %CATALINA_HOME%\lib\servlet-api.jar returnMsg.java,將 .class 放入 classes 目錄。啟動 Tomcat 驗證:https://localhost:8080/6D1/returnMsg 應顯示資料庫內容。
6D1NetMainapps/6D1/src/import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class NetMain extends MIDlet implements CommandListener {
private Display display;
private SendMsg sender;
private Command cmdConnect = new Command("連接", Command.OK, 1);
public NetMain() {
display = Display.getDisplay(this);
}
public void startApp() {
Form form = new Form("聯網測試");
form.append("點選下方按鈕連接伺服器");
form.addCommand(cmdConnect);
form.setCommandListener(this);
display.setCurrent(form);
}
public void pauseApp() {}
public void destroyApp(boolean un) {}
public void commandAction(Command c, Displayable d) {
if (c == cmdConnect) {
sender = new SendMsg(this);
display.setCurrent(sender);
}
}
}
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
public class SendMsg extends Canvas implements Runnable {
private NetMain parent;
private String response = "連線中...";
private Thread thread;
public SendMsg(NetMain parent) {
this.parent = parent;
thread = new Thread(this);
thread.start();
}
protected void paint(Graphics g) {
g.setColor(0xFFFFFF);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0x000000);
g.drawString(response, 5, 5, Graphics.TOP | Graphics.LEFT);
}
public void run() {
HttpConnection conn = null;
DataInputStream dis = null;
try {
conn = (HttpConnection) Connector.open(
"https://localhost:8080/6D1/returnMsg");
conn.setRequestMethod(HttpConnection.GET);
dis = new DataInputStream(conn.openDataInputStream());
StringBuilder sb = new StringBuilder();
String line;
while ((line = dis.readUTF()) != null) {
sb.append(line).append("\n");
}
response = sb.toString();
} catch (Exception e) {
response = "錯誤: " + e.getMessage();
e.printStackTrace();
} finally {
try { if (dis != null) dis.close(); } catch (Exception ignore) {}
try { if (conn != null) conn.close(); } catch (Exception ignore) {}
}
repaint();
}
// 按任意鍵返回主選單
protected void keyPressed(int keyCode) {
parent.display.setCurrent(parent);
}
}
| 層面 | 說明 |
|---|---|
| 通訊協定 | HTTP GET,支援所有 MIDP 裝置 |
| 資料格式 | DataOutputStream/DataInputStream (UTF 字串),簡單輕量 |
| 資料庫連線 | Servlet 端使用 JDBC-ODBC Bridge (舊版範例),生產環境建議改用 DataSource (JNDI) + 連線池 |
| 錯誤處理 | 用戶端捕捉 IOException,顯示友善訊息;伺服器端記錄堆疊追蹤 |
| 安全性 | 範例未加密,實務上必須使用 HTTPS + 驗證機制 |
HttpConnection 的 POST 傳遞參數,支援複雜查詢此架構雖屬經典,但「薄用戶端 + 中介層 + 資料庫」的核心思想至今仍是行動企業應用的基石。