欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
從JavaEE到JavaME的通訊
 
前言
 
本文源于 2005 年底一個(gè)真實(shí)的手機項目。很早就想為那個(gè)項目寫(xiě)點(diǎn)什么了,至今才提筆,也算是了卻一個(gè)心愿。雖然時(shí)隔兩年,但技術(shù)本身并沒(méi)有發(fā)生什么太大的變化,我想本文應該能為廣大開(kāi)發(fā)人員提供幫助吧。
 
受朋友之托,他們接到一個(gè)手機應用項目(以下簡(jiǎn)稱(chēng) dbMobile )。 dbMobile 項目主要服務(wù)于零擔物流運輸,為廣大的貨主和司機建立一個(gè)暢通的交流平臺,實(shí)現便利的貨主找車(chē),車(chē)主找貨功能。只要貨主或車(chē)主的手機支持 Java ,安裝注冊之后以用戶(hù)身份登錄上去,就能免費查詢(xún)自己想要的信息。本文講貫穿整個(gè) dbMobile 項目,并重點(diǎn)介紹開(kāi)發(fā)者最關(guān)注的內容。
 
手機端實(shí)現
 
(由于我是做 Java EE 應用的,為了讓自己以后參考,所以關(guān)于手機端實(shí)現寫(xiě)得較啰嗦。)要進(jìn)行 Java ME 開(kāi)發(fā),首先到 http://java.sun.com/products/sjwtoolkit/download-2_5.html 下載 WTK 2.5 ,然后一步步安裝好(發(fā)現安裝界面比 2.2 漂亮了)。接著(zhù)下載 IDE 插件,我用的開(kāi)發(fā)環(huán)境是 Eclipse ,在 http://eclipseme.org/ 找到 EclipseME 的安裝包 eclipseme.feature_1.7.5_site ,解壓縮之后(也可以不解壓縮,只是安裝方式稍有不同)在 Eclipse 里面新建一個(gè) “New Local Site…” ,定位到剛才插件解壓縮之后的位置,一步步安裝即可。重啟 Eclipse 之后可以在 “Preferences” 選項中發(fā)現 “J2ME” 菜單,現在開(kāi)始配置 “WTK Root” ,如圖一所示。
 
                                    圖一: EclipseME 配置 1
 
配置好 WTK Root 之后,我們還要為 dbMobile 配置設備。如圖二所示,點(diǎn)擊 “Device Management” ,在 “Specify search directory” 中選中 WTK 根目錄,然后點(diǎn)擊右下位置的 “Refresh” ,稍等片刻, WTK 默認的四個(gè)模擬設備就被找到了。

              

                             圖二: EclipseME 配置 2
 
完成了這些,如果沒(méi)有特殊要求,其他選項就不用再配置了。
接著(zhù)新建一個(gè)名為 dbMobile J2ME 項目(既新建 “J2ME Midlet Suit” ),如果你沒(méi)有安裝多個(gè) WTK 版本或者不想使用默認的彩色模擬器的的話(huà),在新建項目的時(shí)候,無(wú)需進(jìn)行過(guò)多的配置。
 
MIDlet MIDP 的基本執行單元,如同 Servlet 繼承自 javax.servlet.http.HttpServlet 一樣, MIdlet 必須繼承自 javax.microedition.midlet.MIDlet 抽象類(lèi)。該類(lèi)定義了三個(gè)抽象方法, startApp() 、 pauseApp() 、 destroyApp() ,應用程序管理器通過(guò)上面這三個(gè)方法控制著(zhù) MIdlet 的生命周期。在編寫(xiě) MIDlet 時(shí)必須實(shí)現這三個(gè)方法。如圖三所示,我為 dbMobile 創(chuàng )建了 HttpCli 類(lèi),該類(lèi)不屬于任何的包。

                             

                                   圖三:創(chuàng )建 Midlet
 
我們來(lái)看看,類(lèi)里面怎樣實(shí)現抽象方法的,并以如何在啟動(dòng)時(shí)進(jìn)入菜單畫(huà)面(登錄前)這個(gè)功能切入。

import  javax.microedition.lcdui.Display;
import  javax.microedition.midlet.MIDlet;
import  javax.microedition.midlet.MIDletStateChangeException;
import  com.forbidden.screen.Navigator;

/*
 * MIDlet 主程序
 * @author rosen jiang
 * @since 2005-12
 
*/
public   class  HttpCli  extends  MIDlet {

    
/**
     * 構造函數
     
*/
    
public  HttpCli() {
          Navigator.midlet 
=   this ;
          Navigator.display 
=  Display.getDisplay( this );
    }

    
/**
     * 啟動(dòng)方法
     
*/
    
public   void  startApp(){
        Navigator.current 
=  Navigator.MAIN_SCREEN;
        Navigator.show();
    }

    
/**
     * 暫停方法
     
*/
    
protected   void  pauseApp() {
        
//  TODO Auto-generated method stub
    }
    
    
/**
     * 銷(xiāo)毀方法
     
*/
    
protected   void  destroyApp( boolean  arg0)  throws  MIDletStateChangeException {
        
this .notifyDestroyed();
    }
}

我們在構造函數 HttpCli() 用到了名叫 Navigator 的導航類(lèi),該類(lèi)的主要作用是把 dbMobile 中所有的頁(yè)面管理起來(lái)、統一進(jìn)行頁(yè)面跳轉控制(稍后我會(huì )把 Navigator 類(lèi)代碼列出來(lái))。接著(zhù)看構造函數, “Navigator.midlet = this” 的作用是把整個(gè) MIDlet 實(shí)例交給導航類(lèi),以便在退出程序時(shí)觸發(fā)。 “Navigator.display = Display.getDisplay(this)” ,在手機屏幕上顯示一幅畫(huà)面就是一個(gè) Display 對象要實(shí)現的功能,從 MIDlet 實(shí)例中獲取 Display 對象實(shí)例,也就是在向導航類(lèi)授予一個(gè)進(jìn)行畫(huà)面切換的控制權。接著(zhù)看 “startApp () 啟動(dòng)方法,同樣調用了導航類(lèi),并設置啟動(dòng)后首先進(jìn)入的頁(yè)面是菜單畫(huà)面(登錄前)。
 
接下來(lái)我們看看 Navigator 導航類(lèi)都有些什么。

package  com.forbidden.screen;

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

/*
 * 導航類(lèi)
 * @author rosen jiang
 * @since 2005-12
 
*/
public   class  Navigator{
    
// 菜單畫(huà)面(登錄前)
     final   public   static   int  MAIN_SCREEN  =   1 ;
    
// 用戶(hù)注冊
     final   public   static   int  USER_REG  =   2 ;
    
// 車(chē)主找貨
     final   public   static   int  AUTO_FIND_GOODS  =   3 ;
    
// 用戶(hù)登錄
     final   public   static   int  USER_LOGIN  =   4 ;
    
// 菜單畫(huà)面(登錄后)
     final   public   static   int  MENU_SCREEN  =   5 ;
    
// 貨主找車(chē)
     final   public   static   int  GOODS_FIND_AUTO  =   6 ;
    
// 空車(chē)信息發(fā)布
     final   public   static   int  AUTO_PUB  =   7 ;
    
// 貨物信息發(fā)布
     final   public   static   int  GOODS_PUB  =   8 ;
    
// 注冊信息更新
     final   public   static   int  REG_UPD  =   9 ;

    
public   static  MIDlet midlet;
    
public   static  Display display;
    
// 當前位置
     public   static   int  current;

    
/**
     * 轉向要顯示的菜單
     
*/
    
public   static   void  show (){
        
switch  (current){
            
case  MAIN_SCREEN:
                display.setCurrent(MainScreen.getInstance());
                
break  ;
            
case  USER_REG:
                display.setCurrent(UserReg.getInstance());
                
break  ;
            
case  AUTO_FIND_GOODS:
                display.setCurrent(AutoFindGoods.getInstance());
                
break  ;
            
case  USER_LOGIN:
                display.setCurrent(LoginScreen.getInstance());
                
break  ;
            
case  MENU_SCREEN:
                display.setCurrent(MenuScreen.getInstance(
null ));
                
break  ;
            
case  GOODS_FIND_AUTO:
                display.setCurrent(GoodsFindAuto.getInstance());
                
break  ;
            
case  AUTO_PUB:
                display.setCurrent(AutoPub.getInstance());
                
break  ;
            
case  GOODS_PUB:
                display.setCurrent(GoodsPub.getInstance());
                
break  ;
            
case  REG_UPD:
                display.setCurrent(RegUpd.getInstance(
null null null null ));
                
break  ;
        }
    }
    
    
/**
     * 導航器定位目標表單
     * 
     * 
@param  String cmd 輸入的命令
     
*/     
    
public   static   void  flow(String cmd){
        
if (cmd.equals( " 離開(kāi) " )){
            midlet.notifyDestroyed();
        } 
else   if  (cmd.equals( " 注冊 " )){
            current 
=  USER_REG;
            show ();
        } 
else   if  (cmd.equals( " 車(chē)主找貨 " )){
            current 
=  AUTO_FIND_GOODS;
            show ();
        } 
else   if  (cmd.equals( " 登陸 " )){
            current 
=  USER_LOGIN;
            show ();
        } 
else   if  (cmd.equals( " 功能列表 " )){
            current 
=  MENU_SCREEN;
            show ();
        } 
else   if  (cmd.equals( " 返回菜單 " )){
            current 
=  MAIN_SCREEN;
             show ();
        } 
else   if  (cmd.equals( " 貨主找車(chē) " )){
            current 
=  GOODS_FIND_AUTO;
            show ();
        } 
else   if  (cmd.equals( " 空車(chē)信息發(fā)布 " )){
            current 
=  AUTO_PUB;
            show ();
        } 
else   if  (cmd.equals( " 貨物信息發(fā)布 " )){
            current 
=  GOODS_PUB;
            show ();
        } 
else   if  (cmd.equals( " 修改注冊信息 " )){
            current 
=  REG_UPD;
            show ();
        }
    }
}

該類(lèi)對每個(gè)畫(huà)面進(jìn)行了編號處理, “show()” 方法是整個(gè)導航類(lèi)的關(guān)鍵,當符合條件的畫(huà)面編號被找到時(shí),調用 “display.setCurrent()” 方法設置被顯示畫(huà)面的實(shí)例,同時(shí)手機上也會(huì )切換到相應畫(huà)面。 “flow()” 方法做用是捕獲用戶(hù)的控制命令,并把命令轉換成內部的畫(huà)面編號,和 “show()” 聯(lián)合使用就能響應用戶(hù)操作了。
 
下面是菜單畫(huà)面(登錄前)類(lèi)。

package  com.forbidden.screen;

import  javax.microedition.lcdui. * ;

/*
 * 菜單畫(huà)面(登錄前)
 * @author rosen jiang
 * @since 2005-12
 
*/
public   class  MainScreen  extends  List  implements  CommandListener{

    
// 對象實(shí)例
     private   static  Displayable instance;

    
/**
     * 獲取對象實(shí)例
     
*/
    
synchronized   public   static  Displayable getInstance(){
        
if  (instance == null )
            instance 
= new  MainScreen();
            
return  instance;
    }

    
/**
     * 畫(huà)面內容
     
*/
    
private  MainScreen(){
        
super  ( " 菜單 " , Choice.IMPLICIT);
        append (
" 注冊 " , null );
        append (
" 登陸 " , null );
        addCommand(
new  Command( " 進(jìn)入 " ,Command.OK, 1 ));
        addCommand(
new  Command( " 離開(kāi) " ,Command.EXIT, 1 ));
        setCommandListener(
this );
    }

    
/**
     * 對用戶(hù)輸入命令作出反應
     * 
@param   c 命令
     * 
@param   s Displayable 對象 
     
*/
    
public   void  commandAction(Command c, Displayable s){
        String cmd 
=  c.getLabel();
        
if  (cmd.equals( " 進(jìn)入 " )){
            String comd 
=  getString(getSelectedIndex());
            Navigator.flow(comd);
        } 
else   if  (cmd.equals( " 離開(kāi) " )) {
              Navigator.flow(cmd);
        }
    }
}

                                                   

                    圖四:高級界面類(lèi)圖
 
Displayable 是所有高級(Screan)、低級(Canvas)界面的父類(lèi),在 dbMobile 項目中,由于專(zhuān)注于數據而不是界面,所以我決定采用高級界面。圖四列出了高級界面的類(lèi)、接口關(guān)系,可以對整個(gè)高級界面開(kāi)發(fā)有個(gè)概括。關(guān)于高級界面編程基礎的話(huà)題就不多說(shuō)了,請參考其他資料。
 
在整個(gè)程序加載的時(shí)候會(huì )首先實(shí)例化HttpCli類(lèi),接著(zhù)觸發(fā)”Navigator.MAIN_SCREEN”,最后實(shí)例化MainScreen類(lèi),在手機屏幕上顯示如圖五的畫(huà)面。MainScreen類(lèi)的getInstance()”方法返回 MainScreen 唯一對象實(shí)例。在“MainScreen()”構造函數中,“super ("菜單", Choice.IMPLICIT)”創(chuàng )建名為菜單的單選列表,然后分別用“append("注冊",null)”“append ("登陸",null)”追加兩個(gè)選項,接著(zhù)追加兩個(gè)命令“addCommand(new Command("進(jìn)入",Command.OK,1))”“addCommand(new Command("離開(kāi)",Command.EXIT,1))”,最后針對當前對象實(shí)例設置命令監聽(tīng)器“setCommandListener(this)”。在手機上一切都已正確顯示后就可以監聽(tīng)用戶(hù)的操作了,“commandAction()”方法捕捉用戶(hù)點(diǎn)擊的是離開(kāi)還是進(jìn)入。如果是離開(kāi),直接利用Navigator類(lèi)退出整個(gè)程序,如果是進(jìn)入則通過(guò)String comd = getString(getSelectedIndex())”代碼獲取用戶(hù)選擇的菜單,然后再通過(guò)Navigator類(lèi)的flow()”方法實(shí)例化相應的畫(huà)面實(shí)例,就像進(jìn)入菜單畫(huà)面(登錄前)一樣。


                                           

                                              圖五:主菜單(登錄前)
 
可能你非常熟悉以上這些調用流程,本文到這里開(kāi)始轉到如何與 Java EE服務(wù)器端通訊的部分。

                                                               
                  圖六:主菜單(登錄后)
 
登錄成功以后進(jìn)入主菜單(登錄后)如圖六所示,現在我重點(diǎn)介紹貨主找車(chē)這個(gè)功能,首先要創(chuàng )建貨主找車(chē)界面,GoodsFindAuto類(lèi)代碼如下:

package com.forbidden.screen;

import java.util.Date;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.DateField;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;

import com.forbidden.thread.GoodsFindAutoThread;
import com.forbidden.vo.TransAuto;

/* 貨主找車(chē)輸入查詢(xún)條件頁(yè)面
 * @author rosen jiang
 * @since 2005-12
 
*/
public class GoodsFindAuto extends Form implements CommandListener {

    
//車(chē)輛出發(fā)地
    private TextField autoFromField;
    
//車(chē)輛目的地
    private TextField autoTargetField;
    
//發(fā)布時(shí)間
    private DateField pubDateField;
    
//對象實(shí)例
    private static Displayable instance;
    
    
/**
     * 獲取對象實(shí)例
     
*/
    
synchronized public static Displayable getInstance(){
        
if (instance==null)
        instance 
= new GoodsFindAuto("貨主找車(chē)");
        
return instance;
    }

    
/**
     * 畫(huà)面內容
     
*/
    
public GoodsFindAuto(String arg0) {
        
super(arg0);
        autoFromField 
= new TextField("車(chē)輛出發(fā)地""28"25, TextField.NUMERIC);
        autoTargetField 
= new TextField("車(chē)輛目的地"null25, TextField.NUMERIC);
        pubDateField 
= new DateField("發(fā)布日期", DateField.DATE);
        pubDateField.setDate(
new Date());
        append(autoFromField);
        append(autoTargetField);
        append(pubDateField);
        Command backCommand 
= new Command("功能列表", Command.BACK, 1);
        Command sendCommand 
= new Command("查詢(xún)", Command.SCREEN, 1);
        addCommand(backCommand);
        addCommand(sendCommand);
        setCommandListener(
this);
    }

    
/**
     * 對用戶(hù)輸入命令作出反應
     * 
@param  c 命令
     * 
@param  s Displayable 對象 
     
*/
    
public void commandAction(Command c, Displayable s) {
        String cmd 
= c.getLabel();
        
if (cmd.equals("查詢(xún)")){
            String autoFrom 
= autoFromField.getString();
            String autoTarget 
= autoTargetField.getString();
            
if (autoTarget.length()==0) {
                Alert a 
= new Alert("提示信息""目的城市不能為空!"null, AlertType.ERROR);
                a.setTimeout(Alert.FOREVER);
                Navigator.display.setCurrent(a);
                
return;
            }
            String pubDate 
= pubDateField.getDate().getTime()+"";
            
//發(fā)送查詢(xún)
            TransAuto ta = new TransAuto(null,null,null,null,
                    pubDate,autoFrom,autoTarget, 
null);
            GoodsFindAutoThread gfat 
= new GoodsFindAutoThread(1,20,ta);
            Navigator.display.setCurrent(WaitForm.getInstance());
            gfat.start();
        }
else{
            Navigator.flow(cmd);
        }
    }
}

對于手機用戶(hù)來(lái)說(shuō),要用最簡(jiǎn)單的界面實(shí)現查詢(xún)功能那是最好不過(guò)了。在構造函數里面添加了三個(gè)輸入框"車(chē)輛出發(fā)地"、"車(chē)輛目的地"、發(fā)布日期,為了更進(jìn)一步減少用戶(hù)輸入,在"車(chē)輛出發(fā)地"車(chē)輛目的地"是按照當地的去掉0的電話(huà)區號來(lái)作為條件,默認的以成都(28)為車(chē)輛出發(fā)地,運行效果如圖七所示。

 
                    圖七:貨主找車(chē)
 
當用戶(hù)完成查詢(xún)并點(diǎn)擊查詢(xún)之后,要對用戶(hù)的輸入信息進(jìn)行判斷,根據業(yè)務(wù)上的要求,車(chē)輛目的地是必填項,如果為空,在commandAction()方法中會(huì )通過(guò)Alert對象進(jìn)行提示。接下來(lái)將與服務(wù)器進(jìn)行數據交互,交互之前先把查詢(xún)條件構造成TransAuto車(chē)輛對象實(shí)例并進(jìn)行序列化,然后再通過(guò)HTTP GET方法請求服務(wù)器,服務(wù)器收到序列化的數據后抽取查詢(xún)條件。手機端和服務(wù)器端通訊的策略是:從手機端到服務(wù)器端是通過(guò)拼接字符串然后GET過(guò)去,而從服務(wù)器端到手機端則通過(guò)UTF-8編碼后的數據流送回來(lái),否則容易出現亂碼。如果你要問(wèn)為什么不使用GBK、GB2312編碼輸出,我的回答是DataOutputStream/ DataInputStream類(lèi)原生支持”writeUTF()/readUTF()”方法,無(wú)論是在服務(wù)器端還是手機端,轉換起來(lái)很輕松,盡管UTF-8三字節編碼會(huì )產(chǎn)生更多的通訊流量。GoodsFindAutoThread(1,20,ta)”構造函數來(lái)自GoodsFindAutoThread線(xiàn)程類(lèi),該線(xiàn)程類(lèi)用于遠程HTTP連接,由于GPRS連接非常慢,為了提高網(wǎng)絡(luò )利用率,要一次多傳些查詢(xún)結果到手機端,這就涉及到了分頁(yè),我定義的分頁(yè)策略是:一次從服務(wù)器端取最多20條記錄,然后在手機上分成4頁(yè)顯示(每頁(yè)5條);如果總記錄數超過(guò)20條,當手機將要閱讀第5頁(yè)的時(shí)候再取下20條。那么上面的構造函數實(shí)際上是發(fā)出了獲取從14頁(yè)共20條數據的分頁(yè)請求。在進(jìn)入線(xiàn)程類(lèi)的話(huà)題之前,先看看TransAuto車(chē)輛類(lèi)。

package com.forbidden.vo;

import java.io.DataInputStream;
import java.io.IOException;

import com.forbidden.util.Split;

/* 車(chē)輛
 * @author rosen jiang
 * @since 2005-12
 
*/
public class TransAuto{

    
//車(chē)主名
    private String name;
    
//車(chē)牌號
    private String autoNo;
    
//聯(lián)系電話(huà)
    private String phone;
    
//車(chē)輛容積
    private String autoCap;
    
//發(fā)布時(shí)間
    private String pubDate;
    
//車(chē)輛出發(fā)地
    private String autoFrom;
    
//車(chē)輛目的地
    private String autoTarget;
    
//備注
    private String memo;

    
/**
     * 構造函數
     * 
     * 
@param name          車(chē)主名
     * 
@param autoNo        車(chē)牌號
     * 
@param phone         聯(lián)系電話(huà)
     * 
@param autoCap       車(chē)輛容積
     * 
@param pubDate       發(fā)布時(shí)間
     * 
@param autoFrom      車(chē)輛出發(fā)地
     * 
@param autoTarget    車(chē)輛目的地
     * 
@param memo          備注
     
*/
    
public TransAuto(String name, String autoNo,
            String phone,String autoCap, String pubDate,
            String autoFrom,String autoTarget,String memo) {
        
this.name=name;
        
this.autoNo=autoNo;
        
this.phone=phone;
        
this.autoCap=autoCap;
        
this.pubDate=pubDate;
        
this.autoFrom=autoFrom;
        
this.autoTarget=autoTarget;
        
this.memo=memo;
    }

    
/**
     * 序列化
     * 
     * 
@return 字符串
     
*/
    
public String serialize() {
        String outStrings 
= "pubDate="+pubDate+"&autoFrom="
        
+autoFrom+"&autoTarget="+autoTarget;
        
return outStrings;
    }

    
/**
     * 多對象的反序列化
     * 
     * 
@param from         車(chē)輛出發(fā)地
     * 
@param rows         條數
     * 
@param din          輸入流
     * 
@return TransAuto[] 車(chē)輛數組
     * 
@throws IOException
     
*/
    
public TransAuto[] deserializes(String from,int rows,DataInputStream din) throws IOException {
        TransAuto[] tas 
= new TransAuto[rows];
        
for (int i = 0; i < rows; i++) {
                String recString 
= null;
            
try{
                recString 
= din.readUTF();
                
if(recString.equals("")){
                    
break;
                }
            }
catch(Exception e){
                
break;
            }
            String[] recStrings 
= Split.split(recString,"&");
            
try{
            name 
= recStrings[0];
            autoNo 
= recStrings[1];
            phone 
= recStrings[2];
            autoCap 
= recStrings[3];
            pubDate 
= recStrings[4]+"時(shí)";
            autoFrom 
= from;
            autoTarget 
= recStrings[5];
            memo 
= recStrings[6];
            }
catch(ArrayIndexOutOfBoundsException e){
                
break;
            }
            TransAuto ta 
= new TransAuto(name,autoNo,phone,
                    autoCap,pubDate,autoFrom,autoTarget,memo);
            tas[i]
=ta;
        }
        
return tas;
    }
    
    
public String getAutoCap() {
        
return autoCap;
    }
    
public void setAutoCap(String autoCap) {
        
this.autoCap = autoCap;
    }
    
public String getAutoFrom() {
        
return autoFrom;
    }
    
public void setAutoFrom(String autoFrom) {
        
this.autoFrom = autoFrom;
    }
    
public String getAutoNo() {
        
return autoNo;
    }
    
public void setAutoNo(String autoNo) {
        
this.autoNo = autoNo;
    }
    
public String getAutoTarget() {
        
return autoTarget;
    }
    
public void setAutoTarget(String autoTarget) {
        
this.autoTarget = autoTarget;
    }
    
public String getName() {
        
return name;
    }
    
public void setName(String name) {
        
this.name = name;
    }
    
public String getMemo() {
        
return memo;
    }
    
public void setMemo(String memo) {
        
this.memo = memo;
    }
    
public String getPhone() {
        
return phone;
    }
    
public void setPhone(String phone) {
        
this.phone = phone;
    }
    
public String getPubDate() {
        
return pubDate;
    }
    
public void setPubDate(String pubDate) {
        
this.pubDate = pubDate;
    }
}

序列化方法serialize()很簡(jiǎn)單,僅僅是按照HTTP GET方法的格式進(jìn)行查詢(xún)條件組裝,就像之前說(shuō)到的,這里因為沒(méi)有涉及到中文字符,所以無(wú)需進(jìn)行UTF-8編碼轉換。”deserializes()”方法進(jìn)行多對象的反序列化,并構造成TransAuto數組在手機上顯示,需要強調的是根據分頁(yè)策略,進(jìn)行一次反序列化的TransAuto對象實(shí)例條數最多20條。服務(wù)器端返回的數據并不是按照HTTP GET方法的格式,而是根據表中字段的順序再在中間加”&”進(jìn)行分割的字符串,遺憾的是手機上String對象未提供”split()”方法,”Split.split(recString,"&")”方法化解了這一問(wèn)題,下面是實(shí)現代碼(來(lái)自于互聯(lián)網(wǎng))。

    /**
     * 分割字符串
     * 
     * 
@param original    需要分割的字符串
     * @paran regex       表達式
     * 
@return 分割后生成的字符串數組
     
*/
    
public static String[] split(String original, String regex) {
        
int startIndex = 0;
        Vector v 
= new Vector();
        String[] str 
= null;
        
int index = 0;
        startIndex 
= original.indexOf(regex);
        
while (startIndex < original.length() && startIndex != -1) {
            String temp 
= original.substring(index, startIndex);
            v.addElement(temp);
            index 
= startIndex + regex.length();
            startIndex 
= original.indexOf(regex, startIndex + regex.length());
        }
        v.addElement(original.substring(index 
+ 1 - regex.length()));
        str 
= new String[v.size()];
        
for (int i = 0; i < v.size(); i++) {
            str[i] 
= (String) v.elementAt(i);
        }
        
return str;
    }
 
一旦所有前期工作都準備好,將是最關(guān)鍵的GoodsFindAutoThread線(xiàn)程類(lèi)連接服務(wù)器返回數據,為了讓界面美觀(guān),在進(jìn)入線(xiàn)程類(lèi)之后GoodsFindAuto類(lèi)馬上通過(guò)Navigator.display.setCurrent(WaitForm.getInstance())”代碼把畫(huà)面轉移到WaitForm,一個(gè)等待畫(huà)面,上面寫(xiě)著(zhù)“正在連接服務(wù)器,請稍等...”,直到線(xiàn)程類(lèi)和服務(wù)器交互完畢,這個(gè)畫(huà)面將由線(xiàn)程類(lèi)負責切換。
 
package com.forbidden.thread;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.InputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.rms.RecordStore;

import com.forbidden.screen.*;
import com.forbidden.util.Split;
import com.forbidden.vo.TransAuto;

/* 貨主找車(chē)線(xiàn)程
 * @author rosen jiang
 * @since 2005-12
 
*/
public class GoodsFindAutoThread extends Thread{

    
private String url;            //服務(wù)器地址
    private String autoFrom;       //車(chē)輛出發(fā)地
    private String autoTarget;     //車(chē)輛目的地
    private String pubDate;        //發(fā)布日期

    
/**
     * 構造函數
     * 
     * 
@param page     請求頁(yè)數
     * 
@param perPage  每頁(yè)條數
     * 
@param ta       構造好的條件對象
     
*/
    
public GoodsFindAutoThread(int page,int perPage,TransAuto ta){
        String userName
=null;
        
try {
            
//取出當前用戶(hù)名,以便進(jìn)行數據庫端日志記錄。
            RecordStore rs = RecordStore.openRecordStore("app",false);
            userName 
= new String(rs.getRecord(1));
            rs.closeRecordStore();
        } 
catch (Exception e) {
        }
        
this.url = "http://127.0.0.1:8080/AirTransport/servlet/GoodsFindAuto?userName="
            
+ userName+"&page="+page+"&perPage="+perPage+"&"+ta.serialize();
        
this.autoFrom = ta.getAutoFrom();
        
this.autoTarget = ta.getAutoTarget();
        
this.pubDate = ta.getPubDate();
    }

    
public void run(){
        InputStream is 
= null;
        HttpConnection  c 
= null;
        
try {
            c 
= (HttpConnection)Connector.open(url);
            
            
//接收輸出流
            is = new DataInputStream(c.openInputStream());
            
int i = (int) c.getLength();
            
byte [] recData = new byte[i];
            is.read(recData);
            is.close();
            c.close();
            
            
//未找到符合條件的車(chē)輛
            if (recData[0]+recData[1]!=0) {
                ByteArrayInputStream bin 
= new ByteArrayInputStream(recData);
                DataInputStream din 
= new DataInputStream(bin);
                Alert al 
= new Alert ("查詢(xún)結果",din.readUTF(),null,AlertType.CONFIRMATION);
                al.setTimeout(Alert.FOREVER);
                din.close();
                bin.close();
                Navigator.display.setCurrent(al,GoodsFindAuto.getInstance());
            } 
else {
                
//找到符合條件的車(chē)輛
                
//丟掉兩個(gè)錯誤信息字節數據
                byte[] reRecData = new byte[recData.length-2];
                System.arraycopy(recData,
2,reRecData,0,recData.length-2);
                ByteArrayInputStream bin 
= new ByteArrayInputStream(reRecData);
                
//結果數據輸入流
                DataInputStream dis = new DataInputStream(bin);
                
int count = Integer.parseInt(dis.readUTF());  //總數
                int total = Integer.parseInt(dis.readUTF());  //總頁(yè)數
                int current = Integer.parseInt(dis.readUTF());//當前頁(yè)碼
                TransAuto ta = new TransAuto(nullnullnullnullnullnullnullnull);
                TransAuto[] tas 
= null;
                tas 
= ta.deserializes(autoFrom,20,dis);
                dis.close();
                bin.close();
                Navigator.display.setCurrent(GFAList.getInstance(count,total,current,autoFrom,autoTarget,pubDate,tas));
            }
        } 
catch(Exception e){
            Alert al 
= new Alert ("查詢(xún)發(fā)生錯誤",e.toString(),null,AlertType.ERROR);
            al.setTimeout(Alert.FOREVER);
            Navigator.display.setCurrent(al,GoodsFindAuto.getInstance());
        }
    }
}

GoodsFindAutoThread()構造函數中,首先取出了記錄在RMS中的當前登陸者名,以便服務(wù)器記錄用戶(hù)的查詢(xún)條件,以后為不同的客戶(hù)提供個(gè)性化服務(wù),接著(zhù)把用戶(hù)輸入的檢索條件記錄下來(lái),取第5頁(yè)的時(shí)候要用到,然后按照之前構造好的TransAuto實(shí)例進(jìn)行序列化生成URL字符串。在”run()”方法中,為了判斷是否返回了正確數據,我在服務(wù)器端的代碼中設置了標識,既:如果查詢(xún)結果為0條或服務(wù)器端發(fā)生任何錯誤,那么返回數據的前個(gè)兩字節不為空,反之則亦然。收到正確的查詢(xún)結果之后,先丟棄前兩個(gè)字節,然后轉換成輸入流,”int count = Integer.parseInt(dis.readUTF())”第一組字節流是總記錄數,”int total = Integer.parseInt(dis.readUTF())”第二組字節流是總頁(yè)數,”int current = Integer.parseInt(dis.readUTF())”第三組字節流是當前頁(yè)碼。取完基本信息后,接著(zhù)取車(chē)輛數據,通過(guò)”tas = ta.deserializes(autoFrom,20,dis)”反序列化之后得到TransAuto數組對象。最后進(jìn)入GFAList類(lèi)進(jìn)行數據列表,代碼” Navigator.display.setCurrent(GFAList.getInstance(count,total,current,autoFrom,autoTarget,pubDate,tas))”把檢索條件全部記錄下來(lái),其做用也是為了再次分頁(yè)的需要。

package com.forbidden.screen;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;

import com.forbidden.thread.GoodsFindAutoThread;
import com.forbidden.vo.TransAuto;

/* 貨主找車(chē)列表
 * @author rosen jiang
 * @since 2005-12
 
*/
public class GFAList extends List implements CommandListener{

    
private Command backCommand;
    
private Command funCommand;
    
private Command preCommand;
    
private Command nextCommand;
    
private static String autoFrom;    //車(chē)輛出發(fā)地
    private static String autoTarget;  //車(chē)輛目的地
    private static String pubDate;     //發(fā)布日期
    private static int count;          //總數
    private static int total;          //總頁(yè)數
    private int current;               //當前頁(yè)碼
    private TransAuto[] newTas;        //車(chē)輛數組
    public static Displayable instance;//對象實(shí)例
    
    
/**
     * 獲取對象實(shí)例
     * 
     * 
@param coun       //總數
     * 
@param tot        //總頁(yè)數
     * 
@param curr       //當前頁(yè)碼
     * 
@param from       //車(chē)輛出發(fā)地
     * 
@param target     //車(chē)輛目的地
     * 
@param date       //發(fā)布日期
     * 
@param tas        //車(chē)輛數組
     * 
@return
     
*/
    
synchronized public static Displayable getInstance(int coun,int tot,int curr,String from,String target,String date,TransAuto[] tas){
        autoFrom 
= from;
        count 
= coun;
        autoTarget 
= target;
        pubDate 
= date;
        total 
= tot;
        instance 
= new GFAList(curr,tas,List.IMPLICIT);
        
return instance;
    }
    
    
/**
     * 構造函數
     * 
@param curr       //當前頁(yè)碼
     * 
@param tas        //車(chē)輛數組
     * 
@param i          //表現方式
     
*/
    
public GFAList(int curr,TransAuto[] tas,int i){
        
super(curr+"/"+total+"頁(yè) 共"+count+"條記錄",i);
        
this.current = curr;
        
this.newTas = tas;
        
for(int j=0;j<5;j++){
            
try{
                TransAuto ta 
= null;
                
if(curr%4==0){
                    ta 
= tas[j+15];
                }
else if(curr%4==1){
                    ta 
= tas[j];
                }
else if(curr%4==2){
                    ta 
= tas[j+5];
                }
else if(curr%4==3){
                    ta 
= tas[j+10];
                }
                append(ta.getName()
+","
                        
+ta.getPhone()+".",null);
            }
catch(java.lang.NullPointerException e){
                
break;
            }
        }
        backCommand 
= new Command("貨主找車(chē)", Command.BACK, 1);
        funCommand 
= new Command("詳情", Command.SCREEN, 1);
        preCommand 
= new Command("上一頁(yè)", Command.SCREEN, 1);
        nextCommand 
= new Command("下一頁(yè)", Command.SCREEN, 1);
        addCommand(backCommand);
        addCommand(funCommand);
        addCommand(preCommand);
        addCommand(nextCommand);
        setCommandListener(
this);
    }

    
/**
     * 對用戶(hù)輸入命令作出反應
     * 
@param  c 命令
     * 
@param  s Displayable 對象 
     
*/
    
public void commandAction(Command c, Displayable s) {
        String cmd 
= c.getLabel();
        
if (cmd.equals("貨主找車(chē)")){
            Navigator.flow(cmd);
        
//翻頁(yè)(下一頁(yè))處理
        } else if (cmd.equals("下一頁(yè)")){
            
if(total == current){
                Alert al 
= new Alert ("提示","已到達最后一頁(yè)。",null,AlertType.CONFIRMATION);
                al.setTimeout(Alert.FOREVER);
                Navigator.display.setCurrent(al);
            } 
else if (current % 4 != 0){
                Navigator.display.setCurrent(getInstance(count,total,current
+1,autoFrom,autoTarget,pubDate,newTas));
            
//如果當前頁(yè)已經(jīng)是4的倍數頁(yè),那么連接服務(wù)器取下20條數據。
            } else if (current % 4 == 0){
                TransAuto ta 
= new TransAuto(null,null,null,null,
                        pubDate,autoFrom,autoTarget, 
null);
                GoodsFindAutoThread gfat 
= new GoodsFindAutoThread(current+1,20,ta);
                Navigator.display.setCurrent(WaitForm.getInstance());
                gfat.start();
            }
        
//翻頁(yè)(上一頁(yè))處理
        } else if (cmd.equals("上一頁(yè)")){
            
if(current == 1){
                   Alert al 
= new Alert ("提示","這是第一頁(yè)。",null,AlertType.CONFIRMATION);
                   al.setTimeout(Alert.FOREVER);
                   Navigator.display.setCurrent(al);
            } 
else if ((current - 1% 4 != 0){
                Navigator.display.setCurrent(getInstance(count,total,current
-1,autoFrom,autoTarget,pubDate,newTas));
            
//如果當前頁(yè)已經(jīng)是4的倍數頁(yè),那么連接服務(wù)器取上20條數據。
            } else if ((current - 1% 4 == 0){
                TransAuto ta 
= new TransAuto(null,null,null,null,
                        pubDate,autoFrom,autoTarget, 
null);
                GoodsFindAutoThread gfat 
= new GoodsFindAutoThread(current-1,20,ta);
                Navigator.display.setCurrent(WaitForm.getInstance());
                gfat.start();
            }
        
//詳情處理
        } else if (cmd.equals("詳情")){
            
if(current % 4 == 0){
                Navigator.display.setCurrent(GFAInfo.getInstance(newTas[getSelectedIndex()
+15]));
            } 
else if (current % 4 == 1){
                Navigator.display.setCurrent(GFAInfo.getInstance(newTas[getSelectedIndex()]));
            } 
else if (current % 4 == 2){
                Navigator.display.setCurrent(GFAInfo.getInstance(newTas[getSelectedIndex()
+5]));
            } 
else if (current % 4 == 3){
                Navigator.display.setCurrent(GFAInfo.getInstance(newTas[getSelectedIndex()
+10]));
            }
        }
    }
}

構造函數GFAList除了創(chuàng )建幾個(gè)命令以外,最主要的工作是顯示本頁(yè)數據,通過(guò)當前頁(yè)碼與4取模之后再從TransAuto數組得到準確數據并顯示在屏幕上。還是讓我們先睹為快吧,這次截圖不是模擬器上,而是運行在我的索愛(ài)K700c上真實(shí)環(huán)境,如圖八所示。

                            
  

                                    圖八:車(chē)輛列表
 
看完截圖,回到”commandAction()”方法上,當用戶(hù)進(jìn)行下一頁(yè)操作的時(shí)候,首先判定當前頁(yè)是不是最后一頁(yè),如果是”Alert al = new Alert ("提示","已到達最后一頁(yè)。",null,AlertType.CONFIRMATION)”代碼給用戶(hù)一個(gè)Alert提示。如果當前頁(yè)是4的倍數頁(yè),GoodsFindAutoThread gfat = new GoodsFindAutoThread(current+1,20,ta)”代碼連接服務(wù)器取回下20條數據,這個(gè)時(shí)候要進(jìn)入WaitForm畫(huà)面進(jìn)行等待,就像首次進(jìn)行查詢(xún)一樣,之前一直保存著(zhù)的查詢(xún)參數也就派上用場(chǎng)了。如果還不是4的倍數,Navigator.display.setCurrent(getInstance(count,total,current+1,autoFrom,autoTarget,pubDate,newTas))”這行代碼就把修改后的數據再次送到GFAList對象的構造函數中,重新實(shí)例化畫(huà)面,也就在手機上實(shí)現了不用連接服務(wù)器的快速翻頁(yè)。上一頁(yè)操作和剛才談到的下一頁(yè)操作類(lèi)似,就不多說(shuō)了。如果用戶(hù)點(diǎn)擊詳情看某條車(chē)輛信息的時(shí)候,需要計算被點(diǎn)擊信息所處的絕對位置,比如當前頁(yè)碼正好是4的倍數,那么可以斷定該條信息處于整個(gè)TransAuto數組的末端,也就是最后一頁(yè),然后取得這條記錄的相對位置(例如3)再加上15,就是這條記錄的絕對位置了,其他位置以此類(lèi)推,”Navigator.display.setCurrent(GFAInfo.getInstance(newTas[getSelectedIndex()+15]))”代碼把某個(gè)選中的車(chē)輛信息送入GFAInfo對象以顯示詳細信息。

package com.forbidden.screen;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;

import com.forbidden.vo.TransAuto;

/* 車(chē)輛詳情
 * @author rosen jiang
 * @since 2005-12
 
*/
public class GFAInfo extends Form implements CommandListener{

    
private Command backCommand;
    
private static Displayable instance;
    
    
private TextField nameField;
    
private TextField autoNoFiled;
    
private TextField phoneFiled;
    
private TextField autoCapField;
    
private TextField pubDateField;
    
private TextField autoFromField;
    
private TextField autoTargetField;
    
private TextField memoField;
    
    
/**
     * 獲取對象實(shí)例
     * 
@param ta 車(chē)輛對象
     * 
@return
     
*/
    
synchronized public static Displayable getInstance(TransAuto ta){
        instance 
= new GFAInfo(ta);
        
return instance;
    }

    
/**
     * 構造函數
     * 
     * 
@param ta 車(chē)輛對象
     
*/
    
public GFAInfo(TransAuto ta){
        
super("車(chē)輛詳情");
        backCommand 
= new Command("返回", Command.BACK, 1);
        nameField 
= new TextField("車(chē)主", ta.getName(), 25, TextField.ANY);
        autoNoFiled 
= new TextField("車(chē)牌號", ta.getAutoNo(), 25, TextField.ANY);
        phoneFiled 
= new TextField("電話(huà)", ta.getPhone(), 25, TextField.ANY);
        autoCapField 
= new TextField("重量", ta.getAutoCap(), 25, TextField.ANY);
        pubDateField 
= new TextField("發(fā)布日期", ta.getPubDate(), 25, TextField.ANY);
        autoFromField 
= new TextField("起始地", ta.getAutoFrom(), 25, TextField.ANY);
        autoTargetField 
= new TextField("目的地", ta.getAutoTarget(), 25, TextField.ANY);
        memoField 
= new TextField("備注", ta.getMemo(), 300, TextField.ANY);
        append(nameField);
        append(autoNoFiled);
        append(phoneFiled);
        append(autoCapField);
        append(pubDateField);
        append(autoFromField);
        append(autoTargetField);
        append(memoField);
        addCommand(backCommand);
        setCommandListener(
this);
    }

    
/**
     * 對用戶(hù)輸入命令作出反應
     * 
@param  c 命令
     * 
@param  s Displayable 對象 
     
*/
    
public void commandAction(Command c, Displayable s) {
        Navigator.display.setCurrent(GFAList.instance);
    }
}

GFAInfo 類(lèi)代碼顯得很簡(jiǎn)單了,”getInstance()”方法每次都根據數據的不同重新構造實(shí)例,”GFAInfo()”構造函數則把TransAuto對象屬性一一呈現出來(lái),如圖九所示的畫(huà)面是dbMobile最底層畫(huà)面,手機端實(shí)現也就告一段落了。

 
                        圖九:車(chē)輛詳情
 
服務(wù)器端實(shí)現
 
相比手機端,服務(wù)器端實(shí)現起來(lái)容易多了。采用的數據庫是MySQL,并使用Proxool連接池,去年在我的blog上也做了引見(jiàn),可參考Proxool 0.9.0RC1 發(fā)布》一文。目前最新版本是0.9.0RC3,Proxool的作者基本上一年才僅僅更新一次RC后面的版本,可能明年才更新到0.9.0RC4,可謂慢工出細活。下面是服務(wù)器端的GoodsFindAuto Servlet類(lèi),由于是2年前的代碼,那時(shí)為了簡(jiǎn)便起見(jiàn),我把需要在DAO里做的事情都搬到這個(gè)Servlet了,另外代碼里面應該用事務(wù)保證,我也偷懶了。

package com.forbidden.airtransport.servlet;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.forbidden.airtransport.util.RegCode;

/* 貨主找車(chē)Servlet
 * @author rosen jiang
 * @since 2005-12
 
*/
public class GoodsFindAuto extends HttpServlet {

    
/**
     * 構造函數
     
*/
    
public GoodsFindAuto() {
        
super();
    }

    
/**
     * 銷(xiāo)毀方法
     
*/
    
public void destroy() {
        
super.destroy();
    }

    
/**
     * 貨主找車(chē)功能
     *
     * 
@param request          HttpServletRequest
     * 
@param response         HttpServletResponse
     * 
@throws ServletException
     * 
@throws IOException
     
*/
    
public void doGet(HttpServletRequest request, HttpServletResponse response)
            
throws ServletException, IOException {
        
//電話(huà)區號實(shí)際城市名互轉類(lèi)
        RegCode rc = new RegCode();
        
//用戶(hù)名,用于記載查詢(xún)日志。
        String userName = request.getParameter("userName");
        
//頁(yè)數
        int page = 0;
        String strPage 
= request.getParameter("page");
        
//每頁(yè)條數
        int perPage = 0;
        String strPerPage 
= request.getParameter("perPage");
        
//車(chē)輛出發(fā)地
        String autoFrom = request.getParameter("autoFrom");
        
//車(chē)輛目的地
        String autoTarget = request.getParameter("autoTarget");
        
//發(fā)布日期
        String pubDate = request.getParameter("pubDate");

        
//查詢(xún)日志
        String writeLog = "insert into search_log (userName,flag,f_rom,target,serDate)" +
                        
" values (?,?,?,?,?)";
        
//計算總記錄數
        String countRow = "select count(*) from auto_back where autoFrom=? and autoTarget=? " +
                        
"and TO_DAYS(regDate)=TO_DAYS(?)";
        
//查詢(xún)結果
        String finSql = "select * from auto_back where autoFrom=? and autoTarget=? " +
                        
"and TO_DAYS(regDate)=TO_DAYS(?) limit ?,?";

        
//連接信息
        Connection conn = null;
        PreparedStatement stm 
= null;
        ResultSet rs 
= null;
        
        
//構建輸出流
        response.setContentType("application/octet-stream");
        OutputStream ops 
= response.getOutputStream();
        DataOutputStream dos 
= new DataOutputStream(ops);
        
try {
            
if(userName==null || strPage==null || strPerPage==null || autoFrom==null || 
                    autoTarget
==null || pubDate==null){
                dos.writeUTF(
"非法請求!");
            }
else{
                page 
= Integer.parseInt(strPage);
                perPage 
= Integer.parseInt(strPerPage);
                
//電話(huà)區號轉換到實(shí)際地址
                autoFrom = rc.convent(autoFrom);
                autoTarget 
= rc.convent(autoTarget);
                
                
//獲取連接
                conn = DriverManager.getConnection("proxool.automy");
                
//記錄請求信息
                stm = conn.prepareStatement(writeLog);
                stm.setString(
1,userName);
                stm.setString(
2,"2");
                stm.setString(
3,autoFrom);
                stm.setString(
4,autoTarget);
                Date sDate 
= new Date();                
                stm.setTimestamp(
5,new Timestamp(sDate.getTime()));
                stm.executeUpdate();
                
                
//計算結果集總數
                stm = conn.prepareStatement(countRow);
                Date date 
= new Date(Long.parseLong(pubDate));
                SimpleDateFormat formatter 
= new SimpleDateFormat("yyyy-MM-dd");
                String Fdate 
= formatter.format(date);
                stm.setString(
1,autoFrom);
                stm.setString(
2,autoTarget);
                stm.setString(
3,Fdate);
                rs 
= stm.executeQuery();
                rs.next();
                
int row    = rs.getInt(1);
                
                
if(row==0){
                    dos.writeUTF(
"未找到你要匹配的數據。");
                }
else{
                    
//進(jìn)行查詢(xún)
                    stm = conn.prepareStatement(finSql);
                    
int rows = 0;
                    
if(page==1){
                        rows 
= 0;
                    }
else{
                        rows 
= perPage*((page-1)/4);
                    }
                    stm.setString(
1,autoFrom);
                    stm.setString(
2,autoTarget);
                    stm.setString(
3,Fdate);
                    stm.setInt(
4,rows);
                    stm.setInt(
5,perPage);
                    rs 
= stm.executeQuery();
                    dos.writeUTF(
"");                                  //設置前兩個(gè)字節為空
                    dos.writeUTF(row+"");                              //記錄總數
                    if(row%perPage!=0){
                        dos.writeUTF(Integer.toString(
1+(row/5)));     //總頁(yè)數
                    }else{
                        dos.writeUTF(Integer.toString((row
/5)));       //總頁(yè)數
                    }      
                    dos.writeUTF(Integer.toString(page));              
//當前頁(yè)
                    while(rs.next()){
                        
//創(chuàng )建業(yè)務(wù)數據輸出流
                        String resString = rs.getString(3)+"&"+rs.getString(4)
                            
+"&"+rs.getString(6)+"&"+rs.getString(5)
                            
+"&"+rs.getString(9+"&"
                            
+rs.getString(8)+"&"+rs.getString(10);
                        dos.writeUTF(resString);
                    }
                }        
            }
            
//數據長(cháng)度
            response.setContentLength(dos.size());
        } 
catch (Exception e) {
            e.printStackTrace();
            dos.writeUTF(
"服務(wù)器異常!"+e.toString());
        }
finally{
            
try {
                rs.close();
                stm.close();
                conn.close();
            } 
catch (SQLException e) {
                e.printStackTrace();
            }
            dos.flush();
            dos.close();
            ops.close();
        }
    }

    
/**
     * post方法
     *
     * 
@param request          HttpServletRequest
     * 
@param response         HttpServletResponse
     * 
@throws ServletException
     * 
@throws IOException
     
*/
    
public void doPost(HttpServletRequest request, HttpServletResponse response)
            
throws ServletException, IOException {
    }

    
/**
     * 初始化方法
     *
     * 
@throws ServletException
     
*/
    
public void init() throws ServletException {
    }
}

Servlet 應該都很熟悉了,那就直奔doGet()方法。”RegCode rc = new RegCode()”構造一個(gè)電話(huà)區號到實(shí)際城市名互轉的實(shí)現,實(shí)現方式也就是在數據庫建立一個(gè)“電話(huà)區號—城市名”的一一對應關(guān)系。接著(zhù)通過(guò)”response.setContentType("application/octet-stream")”代碼聲明輸出類(lèi)型。可以搞破壞了,我在瀏覽器中寫(xiě)上http://127.0.0.1:8080/AirTransport/servlet/GoodsFindAuto,GoodsFindAuto Servlet發(fā)現沒(méi)有收到正確的查詢(xún)條件,馬上通過(guò)”dos.writeUTF("非法請求!")”代碼拋出消息。
 
業(yè)務(wù)上要求無(wú)論有沒(méi)有符合條件的結果,都要記錄用戶(hù)查詢(xún)信息;在記錄完查詢(xún)信息后開(kāi)始根據條件去數據庫匹配,如果匹配結果為0就通過(guò)”dos.writeUTF("未找到你要匹配的數據。")”代碼拋出消息;如果>0就取出詳細數據,然后通過(guò)”dos.writeUTF(resString)”代碼循環(huán)輸出數據流,這和之前在手機端實(shí)現中說(shuō)到的“根據表中字段的順序再在中間加”&”進(jìn)行分割的字符串”完全匹配,另外還不能忘了通過(guò)dos.writeUTF("")”設置前兩個(gè)字節為空,讓手機端明白有業(yè)務(wù)數據返回。最后,無(wú)論服務(wù)器端發(fā)生任何異常,都可以通過(guò)dos.writeUTF("服務(wù)器異常!"+e.toString())代碼告訴手機端。
 
如何做得更好
 
開(kāi)發(fā)Java ME應用給我最大的感受是“模擬器是不可靠的(只能相信它70%)”,模擬器運行成功,但是手機上卻出現千奇百怪的問(wèn)題,遇到這樣的困惑只有自己多花時(shí)間、多請教他人才能解決了。關(guān)于Java ME程序的調試,網(wǎng)上有一大把說(shuō)明,我就不拿來(lái)引用了,不過(guò)我照著(zhù)說(shuō)明修改了Eclipse,始終有點(diǎn)問(wèn)題。另外,索愛(ài)和諾基亞都能正常運行,但摩托羅拉手機始終有中文亂碼,這個(gè)問(wèn)題我還沒(méi)解決。如果你很在意勞動(dòng)成果被他人竊取,那么推薦使用ProGuard一個(gè)很好用的壓縮、優(yōu)化、混肴器,在EclipseME插件里有相應的配置,在這里引用一句話(huà)“混淆只是延緩了反編譯的時(shí)間”,自己想想也行,至少有那么一點(diǎn)安全感。另外還有安全性的問(wèn)題,既然以HTTP方式提供服務(wù),那么就應該實(shí)現一種安全策略,我考慮的是類(lèi)似HTTP Session的方式,在登錄成功后服務(wù)器端生成以時(shí)間戳為參考的隨機數返回給手機端,然后接下來(lái)的交互手機端必須提供這個(gè)隨機數進(jìn)行服務(wù)器端驗證,成功后才能獲取業(yè)務(wù)數據,另外還要提供超時(shí)機制。
 
我們知道連接GPRS很慢,但也要關(guān)注這樣的用戶(hù)提問(wèn):“為什么不能訂閱本月內成都到上海的所有車(chē)輛呢?每天沒(méi)事的時(shí)候打開(kāi)程序讓它在后臺運行并自動(dòng)同步數據保存在手機上,當符合條件的車(chē)輛出現時(shí),能自動(dòng)提醒我;不光如此,我還要在月底翻閱這些所有符合條件的車(chē)輛。”
 
依照現有方式,短信推送可實(shí)現自動(dòng)提醒功能,但是無(wú)法實(shí)現數據瀏覽(短信字數有限);WAP方式可以實(shí)現數據瀏覽,但是無(wú)法實(shí)現提醒功能,除非WAP瀏覽器定時(shí)刷新頁(yè)面或支持Ajax,就算支持也不能實(shí)現離線(xiàn)數據瀏覽!
 
問(wèn)題的解決辦法——“在手機上建立分布式數據庫。”目前db4o西班牙團隊領(lǐng)導的db4oME項目正在開(kāi)發(fā)中,該項目能幫助實(shí)現手機分布式數據庫的遐想。我們可以再想得更遠點(diǎn),是不是有了db4oME就能解決上面的問(wèn)題?我認為可以解決,不過(guò)又會(huì )產(chǎn)生更多的問(wèn)題,比如Java能管理手機上多大的存儲空間,是否可以把數據存放在例如TF卡上,如果可以放在TF卡上那么檢索效率如何,數據文件是否安全……
 
要實(shí)現遐想并解釋上面的問(wèn)題有待于廣大開(kāi)發(fā)者的共同努力,把自己的業(yè)余時(shí)間都投入在類(lèi)似db4oME這樣的技術(shù)上,如果這樣的分布式數據庫能成功實(shí)現,我想這會(huì )給移動(dòng)計算帶來(lái)一場(chǎng)革命,更多依托網(wǎng)絡(luò )、數據庫的手機應用程序將會(huì )誕生,發(fā)揮Java強大的優(yōu)勢!
 
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Spring MVC防御CSRF、XSS和SQL注入攻擊
后臺自動(dòng)發(fā)送郵件的程序(Java Mail,WEB版)
主題:java 加密解密簡(jiǎn)單實(shí)現
JAVA MAIL發(fā)送郵件
文件上傳自寫(xiě)代碼實(shí)現servlet3.0,part
java SSH中防止非法登錄 過(guò)濾器的使用
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久