这篇文章将以一个详细的例子介绍这些API,它演示了J2ME设备和一个基于servlet的Web系统可以进行的交互。
作者:mingjava 来源:J2ME开发网 2007年11月21日
关键字:
ScreenCallback 如上所示,VoterMidlet实现了ScreenCallback接口。该接口将UI类和一些事件隐藏起来,否则UI类可能需要一个到MIDlet的引用。ScreenCallback接口包含有一个单一的方法public void exit(),UI屏幕使用这个方法来提醒MIDlet,用户已经按下“Exit”按钮。 通过为ScreenCallback写代码,其它的MIDlet方法就与UI屏幕的开发者无关。这是很重要的,因为如果使用不当,一些MIDlet方法会给程序带来破坏性的后果。 VoteResults VoteResults是一个用户接口类,用来显示投票的结果给用户。为了让例子简化,该接口实现了两个Model-View-Controller类:View和Controller。 该构造器由MIDlet中接收唯一一个参数--ScreenCallback接口。如上所述,该接口可让Screen能够回调MIDlet的一些方法。 构造器初始化该对象并且创建例子的用户界面,以下是其中令人感兴趣的部分: VoteSummary voteSummary = ResourceUtility.getVoteSummary(); initialize(voteSummary); 以上的代码是负责初始化MIDlet和JSP页面的通信,它模拟的是一个真实的系统。ResourceUtility通过HTTP参数访问一个URL,并且由该JSP中得到信息。它使用该信息来创建一个VoteSummary对象。在后面的例子中我们还将进一步讨论这个接口。 然后就会调用initialize()方法来创建UI显示,它包括有两个StringItems显示前面的投票结果,还有一个ChoiceGroup包含有所有可能的投票和相应的投票值: public void initialize(VoteSummary voteSummary) {; append( getNumVotesString( voteSummary.getNumVotes() )) ; append( getAvgVoteString( voteSummary.getAvgVote() )); append( showVoteResults( voteSummary.getVotes() )); }; 当用户输入时,就会调用commandAction()方法。该方法接收设备的输入。如果输入的命令是“Vote”,当前的选项就会由ChoiceGroup中得到。这时就会构造一个Vote对象,并且传送给ResourceUtility.addEntry()方法。该方法就会将信息传送给JSP,JSP就会将新投票加入到记录中,并且返回一个更新的VoteSummary对象。然后它就会调用update()方法: public void commandAction(Command c, Displayable s) {; String command = c.getLabel(); if ( command.equals("Exit") ) {; _screenCallback.exit(); }; else if ( command.equals("Vote") ) {; // get the selected item int selectedIndex = _voteResults.getSelectedIndex(); Vote newVote = new Vote(""+ selectedIndex, null, null); VoteSummary voteSummary = ResourceUtility.addEntry( newVote); update( voteSummary ); }; }; VoteSummary VoteSummary对象包含有当前投票的状态信息。它跟踪全部的投票数字,平均的投票,以及维护投票的一个Vector(可得到每个选项的投票信息): public VoteSummary(String numVotes, String avgVote, Vector votes) {; _numVotes = numVotes; _avgVote = avgVote; _votes = votes; }; 根据由JSP返回到MIDlet的XML,就会创建VoteSummary对象。 ResourceUtility ResourceUtility类由远程服务器上得到XML信息。它使用HttpConnection由JSP中得到XML,然后就会通过XMLUtil 将这些XML转换为一个VoteSummary 对象: public static VoteSummary getVoteSummary() {; String xml = loadVoteResults(); return convertXMLToVoteSummary( xml); }; 上面的getVoteSummary()方法访问这个对象。该方法会依次调用loadVoteResults()和convertXMLToVoteSummary()方法。loadVoteResults()方法如下所示,它调用了backendComms()方法,该方法用来为后台系统增加投票: public static String loadVoteResults() {; return backendComms(LOAD_URL, ""); }; private static String backendComms(String requestURL, String requeststring) {; HttpConnection httpConnection = null; DataInputStream dataInputStream = null; StringBuffer messagebuffer = new StringBuffer(); String requestString = requestURL + requeststring; Try {; // Open an HTTP connection with the Web server httpConnection = (HttpConnection) Connector.open(requestString, Connector.READ_WRITE); // Set the request method to GET httpConnection.setRequestMethod(HttpConnection.GET); // Retrieve the response back from the servlet dataInputStream = new DataInputStream(httpConnection.openInputStream()); int inputChar; // Check the Content-Length first long contentLength = httpConnection.getLength(); if(contentLength!=-1) {; for(int i = 0;I {; if((inputChar = dataInputStream.read())!= -1) {; messagebuffer.append((char)inputChar); }; }; }; else {; // if the content-length is not available while ((inputChar = dataInputStream.read()) != -1) {; messagebuffer.append((char) inputChar); }; }; dataInputStream.close(); }; catch (IOException ioe) {; messagebuffer = new StringBuffer("ERROR!"); }; catch (Exception e){; e.printStackTrace(); }; finally {; try {; if (httpConnection != null){ httpConnection.close(); }; catch (IOException ignored) {;}; try {; if (dataInputStream != null) dataInputStream.close(); }; catch (IOException ignored) {;}; }; return messagebuffer.toString(); }; 以下我们讨论一下backendComms()方法。首先由try-catch块开始。第一步是打开一个到服务器的读/写HttpConnection。上面我已经说过,该方法得到XML并且对服务器发出写请求,因此我们需要使用一个READ_WRITE连接: try {; // Open an HTTP connection with the Web server httpConnection = (HttpConnection) Connector.open(requestString, Connector.READ_WRITE); // Set the request method to GET httpConnection.setRequestMethod(HttpConnection.GET); // Retrieve the response back from the JSP dataInputStream = new DataInputStream(httpConnection.openInputStream()); 要得到一个HttpConnection实现,我们调用Connector.open()方法。该类包含有静态的方法,可根据连接字符串产生用作通信的相应接口。在这个例子中,我们要得到一个HttpConnection,因此我们将Connector.open()的响应放入HttpConnection接口。 一旦我们发出请求,我们就可以使用HttpConnection对象的openInputStream()方法,通过它可由JSP中得到结果的InputStream: if(contentLength!=-1) {; for(int i = 0;I {; if((inputChar = dataInputStream.read())!= -1) {; messagebuffer.append((char)inputChar); }; }; }; else {; // if the content-length is not available while ((inputChar = dataInputStream.read()) != -1) {; messagebuffer.append((char) inputChar); }; }; 然后就可以读取该响应内容的长度,如果没有找到,你也可以一直读取它直到得到一个EOF或者出现一个错误的字符。每个由DataInputStream读取的字符都被加入到StringBuffer中。这个StringBuffer包含有一个XML表示的投票结果,它将被传送回调用的方法,然后再传送到convertXMLToVoteSummary()方法,如下所示: private static VoteSummary convertXMLToVoteSummary(String xml) {; InputStreamReader insr = new InputStreamReader( new ByteArrayInputStream(xml.getBytes() ) ); VoteSummary voteSummary = null; Try {; voteSummary = XMLUtil.getVoteResults(insr); }; catch (IOException ioe) {;}; return voteSummary; }; 该方法将XML字符串转换为一个Java对象,这样我们就可以使用方法来得到数据,而不是分析数据。我们使用XMLUtil.getVoteResults()方法来做这个转换。在接触该方法前,我们先完成ResourceUtility对象。最后的一个方法是addEntry(),将新的投票传送到JSP。如上所述,为了效率,它再次使用backendComms()方法: public static VoteSummary addEntry(Vote vote) {; StringBuffer requestString = new StringBuffer(); requestString.append(QUESTION + vote.toRequestString() ); String xml = backendComms(LOAD_URL, requestString.toString() ); return convertXMLToVoteSummary(xml); };