作者:Jonathan Knudsen 
翻译:FlyBean 
2002年3月 
下载: HitServlet.java HitMIDlet.java 
在本教程的第一部份,您已经学到了如何写一个简单的Java[tm] 2微型版(J2ME[tm])应用。J2ME[tm]应用,一个MIDlet程序,是为移动信息设备协议子集所设计的。该协议是J2ME中的一个规范。现在激动人心的时刻到了,您将扩展您的视野。您将学习如何编写及发布一个servlet,并且将该servlet与一个MIDlet程序挂接起来。当您阅读完本文之后,您将掌握开发端对端无线Java应用的所有知识。 
本文有两个版本,您可以根据您所希望使用的servlet开发平台来选择: 
当然,每个服务器都有正反两个方面。对于servlet 开发,Tomcat是易于使用的。然而,它的能力也仅限于servlet和JSP。相比这下,J2EE RI服务器实现了J2EE技术的所有领域,包括servlet, JSP, EJB, JMS, JNDI等等。 
您现在所读到的文章所示范的是使用Tomcat来进行servlet开发。点击此处,阅读本文的J2EE RI 服务器版本。 
安装和运行Tomcat 
Tomcat是以ZIP包的形式发布的,您可以从Apache Jakarta 项目下载。在写本文时,它的版本是4.0.2。 
Tomcat的安装过程很简单,您所要做的只是将下载文件解包。您可以将它放于任何您想要放的地方。我是把它解包到根级目录,c:\jakarta-tomcat-4.0.2\。 
Tomcat自身是用Java编写的。要运行它,您需要告诉它J2SE的安装位置。您可以将J2SE的安装位置写到环境变量JAVA_HOME中,来完成这项工作。在我的机器上,环境变量JAVA_HOME的值是c:\jdk1.3.1。 
为了运行Tomcat,您需要打开一个命令窗口。进入Tomcat的bin目录,键入startup并回车。系统将跳出一个新窗口,上面显示了一些初始化信息。 
| 
    Tomcat初始化信息
  |    
您可以使用浏览器检查Tomcat是否是真的运行了:试试打开URL http://localhost:8080/,看看发生了什么。如果Tomcat是正常运行的,那么您应该看到Tomcat的一个默认页面,上面有一些指向servlet 和 JSP例子的链接。 
关闭Tomcat时,另外打开一个命令窗口。进入Tomcat的bin目录,运行shutdown命令。 
启动和停止Tomcat的这种方式略微有些笨拙。我建议您创建Windows快捷方式来运行startup 和 shutdown命令。 
编写Servle源代码 
为您的servlet 编写代码非常类似于编写其它Java源代码:使用您所选择的文本编辑器来创建Java源文件。在本例中,您将编写一个非常简单的servlet,命名为HitServlet。下面展示了它的源代码。HitServlet简单地统计它被调用的次数,并将含有此统计数值的信息发回客户端。(它不是线程安全的,在此处无关紧要。) 
import javax.servlet.http.*; 
import javax.servlet.*; 
import java.io.*; 
public class HitServlet extends HttpServlet { 
  private int mCount; 
  public void doGet(HttpServletRequest request, 
      HttpServletResponse response) 
      throws ServletException, IOException { 
    String message = "Hits: " + ++mCount; 
    response.setContentType("text/plain"); 
    response.setContentLength(message.length()); 
    PrintWriter out = response.getWriter(); 
    out.println(message); 
  } 
} 
稍后,您将以特殊的目录结构建立一个WEB应用。使用该目录结构,服务器可以容易地找到应用所需的各个部份。从现在开始,抱定信念(译者注:意指不要问为什么),将源代码存为Tomcat 根目录下的一个文件,命名为webapps/midp/WEB-INF/classes/HitServlet.java。(现在继续创建midp 目录及其子目录。) 
编译Servlet 
除了一个重要的改变外,编译servlet代码非常接近其它Java开发的编译过程。由于servlet API不是J2SE平台的核心部份,因此在编译servlet之前,需要将它加入CLASSPATH之中。 
Tomcat 根目录下common/lib/servlet.jar 文件包含了servlet API。您只需简单地将此文件加到CLASSPATH中,就可以使用javac编译HitServlet.java。正如Windows示例所演示的寻样,您可以在系统属性中,或是在命令行编辑CLASSPATH: 
C:\>set CLASSPATH=\jakarta-tomcat-4.0.2\common\lib\servlet.jar 
C:\>javac HitServlet.java 
发布Servlet 
为了发布您的servlet,您首先得理解关于Web应用的一些事情。一个Web应用是诸如HML、图像之类的静态内容,servlet以及其它可以通过Web接口访问的资源的集合。进入您的Tomcat安装目录下的webapps目录,您可以看到一些文件(或目录),例如:examples 和 manager。我们将创建一个新的Web应用,并将我们的servlet放在里面。 
首先,我们创建Web应用。您已经在webapps 目录中建立了名为 midp的新目录,这将是您保存servlet源代码的目录。现在您需要编辑Tomcat的一个配置文件,这样,Tomcat才知道这个新的Web应用。使用文本编辑器打开文件conf/server.xml。在该文件中,Web应用被称为上下文(context)。使用滚动条,找到examples Web应用的Context 项目,类似如下内容: 
<!-- Tomcat Manager Context --> 
<Context path="/manager" docBase="manager"  
    debug="0" privileged="true"/> 
为您的新Web应用拷贝整个项目。修改相应的名字为midp并加入reloadable属性: 
<!-- MIDP context --> 
<Context path="/midp" docBase="midp"  
    debug="0" reloadable="true" privileged="true"/> 
将midp上下文项目放在examples 上下文项目下面,保存文件。 
以上所做的这些步骤的是将进来的HTTP请求映射到特定目录中的Web应用。任何进来的以“/midp”(path)开头的HTTP请求都将明确地转交给位于webapps/midp(docBase)的Web应用。reloadable属性对于调试有极大的帮助:它告诉Tomcat自动重新载入任何您所修改后的servlet类,这样您就不必重新启动服务器。 
现在您已经创建了一个Web应用,并充实了内容。Web应用有一个标准目录结构,该目录结构是由servlet规范所要求的。在此,我们不会深入讲述这个问题。Web应用必需的部份是web.xml文件,该文件描述了Web应用的不同部份。它位于每个Web应用的标准目录中,通常存贮为WEB-INF/web.xml。 
现在应该为您的新应用创建一个web.xml文件了。您希望外面的世界可以访问您的servlet。您知道servlet的类名:HitServlet,而且您希望使用类似/hits的路径。请注意:servlet的路径是相对于Web应用的路径的,因此该servlet的全路径将是http://localhost:8080/midp/hits。拷贝下面的文本(或下载),并将它存为Tomcat根目录下的webapps/midp/WEB-INF/web.xml文件: 
<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE web-app 
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"> 
<web-app> 
  <servlet> 
    <servlet-name>bob</servlet-name> 
    <servlet-class>HitServlet</servlet-class> 
  </servlet> 
  <servlet-mapping> 
    <servlet-name>bob</servlet-name> 
    <url-pattern>/hits</url-pattern> 
  </servlet-mapping> 
</web-app> 
该文件告诉Tomcat将名为HitServlet的servlet映射到路径/hits上。servlet-name是web.xml的内部元素,它将servlet元素与servlet-mapping元素链接起来。名字bob仅仅是个友好的示例,您可以选择任何您希望的名字。 
您应记得您已经将您的servlet源代码存放于WEB-INF 目录下名为classes的标准目录中了。该目录是Tomcat期望发现servlet类文件的目录,因此,当您编译了源代码,那么servlet类就存放于正确的位置了。 
现在您的servlet已经发布在您创建的新Web应用中了。但是,请注意,您必须重新启动Tomcat,这样它才认可您对server.xml文件所做的修改。 
打开浏览器,浏览http://localhost:8080/midp/hits,您就可以测试您亲手所做的工作了。您应该能看到HitServlet的输出。重新载入该页面几次,观察点击数的增长。 
For more information on servlet development, see Java Servlet Technology, part of the J2EE Tutorial.  
为了获得有关servlet开发的更多信息,请参看Java Servlet Technology(Java Servlet技术)。该文章是J2EE教程的一部份。 
接通MIDlet与Servlet 
这部份是很有趣的。现在您有了一个既支持MIDP,也支持servlet的开发环境。您将接通这两个世界,创建一个端对端的Java应用。通过HTTP,MIDlet可以连接整个世界,而您刚才所写的servlet可以让整个世界访问。因此,MIDlet连接到servlet是一件非常简单的事情。 
运行KToolbar(J2MEWTK的一部份),打开本教程第一部份所创建的MIDlet工程。您将要创建一个新的MIDlet,它将连接到您的servlet上,取得其输出并显示。如果您还没有创建过J2ME Wireless Toolkit工程,请返回到第一部份,现在就开始创建。下面给出了连接到HitServlet的MIDlet的全部源代码。 
import java.io.*; 
import javax.microedition.io.*; 
import javax.microedition.lcdui.*; 
import javax.microedition.midlet.*; 
public class HitMIDlet 
    extends MIDlet  
    implements CommandListener { 
  private Display mDisplay; 
  private Form mMainForm; 
  private StringItem mMessageItem; 
  private Command mExitCommand, mConnectCommand; 
  public HitMIDlet() { 
    mMainForm = new Form("HitMIDlet"); 
    mMessageItem = new StringItem(null, ""); 
    mExitCommand = new Command("Exit", Command.EXIT, 0); 
    mConnectCommand = new Command("Connect", 
        Command.SCREEN, 0); 
    mMainForm.append(mMessageItem); 
    mMainForm.addCommand(mExitCommand); 
    mMainForm.addCommand(mConnectCommand); 
    mMainForm.setCommandListener(this); 
  } 
  public void startApp() { 
    mDisplay = Display.getDisplay(this); 
    mDisplay.setCurrent(mMainForm); 
  } 
  public void pauseApp() {} 
  public void destroyApp(boolean unconditional) {} 
  public void commandAction(Command c, Displayable s) { 
    if (c == mExitCommand) 
      notifyDestroyed(); 
    else if (c == mConnectCommand) { 
      Form waitForm = new Form("Waiting..."); 
      mDisplay.setCurrent(waitForm); 
      Thread t =  new Thread() { 
        public void run() { 
          connect(); 
        } 
      }; 
      t.start(); 
    } 
  } 
  private void connect() { 
    HttpConnection hc = null; 
    InputStream in = null; 
    String url = getAppProperty("HelloMIDlet.URL"); 
    try { 
      hc = (HttpConnection)Connector.open(url); 
      in = hc.openInputStream(); 
      int contentLength = (int)hc.getLength(); 
      byte[] raw = new byte[contentLength]; 
      int length = in.read(raw); 
      in.close(); 
      hc.close(); 
      // Show the response to the user. 
      String s = new String(raw, 0, length); 
      mMessageItem.setText(s); 
    } 
    catch (IOException ioe) { 
      mMessageItem.setText(ioe.toString()); 
    } 
    mDisplay.setCurrent(mMainForm); 
  } 
} 
HitMIDlet 的主屏幕类似于HelloMIDlet,但是它包括了两个命令:Exit 和 Connect。Connect启动一个独立的线程并调用connect()方法,该方法处理网络连接和获取结果。 
将上面的代码拷贝(或下载)到您的编辑器中,并将之保存为J2MEWTK根目录下apps/HelloSuite/src目录中的名为HitMIDlet.java的文件。 
在HitMIDlet能工作之前,还需要完成其它两项配置。首先,您需要将此新MIDlet的情况告诉J2MEWTK。点击Settings...,然后选择MIDlets页。点击Add并在MIDlet名字和类名中都填入“HitMIDlet”。您可以让Icon项空着。点击OK,您就将看到HelloMIDlet 和 HitMIDlet都列出来了。 
下一步,您需要定义一个系统属性,该属性是HelloMIDlet用来作为其网络连接的URL的(此属性在connect()的第三行取出)。在J2MEWTK中,点击Settings...,然后选择User Defined页。点击Add按钮。填入属性名称为HelloMIDlet.URL,它的值应该是调用HitServlet的URL,该URL就是您测试servlet时在浏览器中使用的URL。完成后,点击OK,关闭工程设置窗口。 
现在,在J2MEWTK中,点击Build构造此工程。假设您没有得到任何错误信息,您现在可以准备测试这个应用了。首先确保您的服务器是处于运行中的。然后在J2MEWTK中,点击Run,选择HitMIDlet。选择Connect命令。如果一切正常,HitMIDlet将调用HitServlet,并在设备仿真器屏幕上显示: 
| 
    成功!
  |    
开发注意事项 
现在,您已经创建了您自己的Web应用,您可以容易地修改和测试HitServlet;只需要改变源代码并重新编译。当下一次您从浏览器或HelloMIDlet调用servlet时,Tomcat 将使用新版本的servlet(还记得Tomcat的 server.xml 文件中的reloadable属性吗?那正是reloadable所表达的意思)。 
如果您想编写另外的servlet,您将可能需要修改您的Web应用的web.xml文件。如果是这样,您将需要弹起(bounce,也就是重新启动)服务器,以使得所做的修改生效。 
总结 
本文展示了如何完整地搭建端对端Java开发环境。第一部份演示了MIDlet开发环境的建立和使用。教程的本部份(也即第二部份)展示了如何配置和使用servlet开发环境。在本部份,您学到了如何安装和运行一个服务器,以及如何编写和发布servlet。然后,您接通了MIDlet世界和servlet世界,创建了一个简单的端对端Java解决方案。 
作为到世界其它部份的起始点,servlet给您指明了通向J2SE和J2EE全部动力的道路。这就是创建强有力的端对端Java应用之路。MIDP相对是小而简单的,但是通过与servlet对话,它们能完成大量工作。 
为了获取更多的端对端Java应用设计的信息,请参看白皮书Wireless Blueprints(无线蓝图)。它提供了使用端对端Java技术创建的示例应用。 
 
 
关于作者:Jonathan Knudsen [电子邮件] [主页]写过几本书,包括Wireless Java(无线Java), The Unofficial Guide to LEGO MINDSTORMS Robots(非正式的LEGO头脑风暴机器人指南), Learning Java(Java学习), and Java 2D Graphics(Java 2D图形)。Jonathan写作内容广泛,主要是Java和Lego机器人,也包括名为Bite-Size Java的每月在线专栏,以及为JavaWorld、EXE、NZZ Folio和O'Reilly Network所写的一些文章。他拥有普林斯顿大学机械工程学位。  
 
  |