AIR 迷你教程 — 在AIR 2.0 程序中嵌入TOMCAT(NativeProcess 实例)

Posted by Kevin Luo at 21 January 2010

Category: AIR 迷你教程

Tags: ,

AIR 2.0 有很多令人期待和振奋的功能,使得AIR向成熟的桌面应用程序开发环境又进了一大步。上一篇文章里介绍了ServerSocket的用法,这篇教程中将向大家介绍NativeProcess,在AIR2.0中我们可以使用程序默认的打开方式直接打开一个外部的应用程序 (file.openWithDefaultApplication()) 或者 通过今天要讲的启动进程方式运行一个程序。

AIR与本地应用程序的交互是AIR 2.0的一个重要更新,这个功能的实现可以帮助我们做到在AIR 1.5时代很难完成的事情,比如我在项目中就需要操作一些硬件,但AIR不能直接操作端口,所以只能借助其他的小程序来实现,现在我们就可以很容易的操作这些小程序以达到操作硬件的目的,而Flex (AIR)与JAVA的结合很早就已经开始了,但由于早期AIR的局限性,想要把JAVA直接部署在客户端还是比较麻烦的事情,但是从AIR2.0开始我们不用担心了。现在我们用很简单的方式就可以在AIR程序中集成TOMCAT, 一次性的将后台与AIR部署到客户端。

程序的原版(Flash Builder 4版)同样是从http://coenraets.org/获得,有兴趣的朋友可以关注这个博客。我的例子仍然使用FLEX 3.

Demo过程

  1. 下载安装 AIR 2.0 beta runtime.
  2. 下载AIRAppWithEmbeddedTomcat..exe 或者 AIRAppWithEmbeddedTomcat.dmg (NativeProcess 必须在程序发布为相应平台的应用程序后才可以使用,发布的方法这里就不介绍了,可以参看http://help.adobe.com/en_US/FlashPlatform/develop/air/building_apps/WS789ea67d3e73a8b22388411123785d839c-8000.html)
  3. 安装运行AIRAppWithEmbeddedTomcat.exe, 修改JAVA_HOME,如果默认的路径不对
  4. 点击 “启动” 可以开启TOMCAT(端口是8080)。在JSP实例和RemoteObject实例中可以看见加载JSP页面和使用RemoteObject获取数据的测试。

控制台

a

JSP 加载测试

b

RemoteObject 测试

c

源代码

?View Code ACTIONSCRIPT3
<?xml version="1.0" encoding="utf-8"?>
<!--www.flextheworld.com-->
<mx:WindowedApplication applicationComplete="init()" xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" height="600" width="800" >
	<mx:Script>
        <![CDATA[
            import mx.controls.Alert;
 
            //用于启动和停止Tomcat的进程
            private var startTomcatProcess:NativeProcess;
            private var stopTomcatProcess:NativeProcess;
 
            private var tomcatHomeDir:File;
 
            public function init():void
            {
                if (!NativeProcess.isSupported)
                {
                    Alert.show("不支持进程控制,请先将程序发布为当前操作系统应用程序");
                }
 
                //如果tomcat不存在,重新复制到app store文件夹
                tomcatHomeDir = File.applicationStorageDirectory.resolvePath("tomcat");
                if (!tomcatHomeDir.exists)
                {
                    var tomcatOriginalDir:File = File.applicationDirectory.resolvePath("tomcat");
                    trace("Copying tomcat to appStorageDirectory...");
                    tomcatOriginalDir.copyTo(tomcatHomeDir);
                    var f:File;
                    f.openWithDefaultApplication()
                }
 
 
                tomcatHome.text = tomcatHomeDir.nativePath;             
 
                // 读取保存的配置(第一次运行以后生成)
                var xml:XML = readConfig();
                if (xml != null)
                {
                    javaHome.text = xml.javaHome;
                    return;
                }
 
                // 如果第一次使用,设置默认Path
                if (Capabilities.os.toLowerCase().indexOf("win") > -1)
                {
                    // 默认的JAVA_HOME (windows)
                    javaHome.text = "C:\\Program Files\\Java\\jdk1.6.0";
                }
                else if (Capabilities.os.toLowerCase().indexOf("mac") > -1)
                {
                    // 默认的JAVA_HOME (Mac)
                    javaHome.text = "/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0";
                }
 
            }
 
            public function startTomcat():void
            {
                // 将本次的JAVA_HOMR写入配置文件
                writeConfig();
 
                log.text = "Starting Tomcat..." + File.lineEnding;
                startTomcatProcess = new NativeProcess();
                execute(startTomcatProcess, "start");
            }
 
            public function stopTomcat():void
            {
                log.text = "Stopping Tomcat..." + File.lineEnding;
                stopTomcatProcess = new NativeProcess();
                execute(startTomcatProcess, "stop");
            }
 
            public function execute(process:NativeProcess, arg:String):void
            {
                // 先获取JVM
                var file:File = new File(javaHome.text);
                if (Capabilities.os.toLowerCase().indexOf("win") > -1)
                {
                    file = file.resolvePath("bin/javaw.exe");
                }
                else
                {
                    file = file.resolvePath("Home/bin/java");
                }
 
                // 启动TOMCAT
                try
                {
                    var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
                    nativeProcessStartupInfo.executable = file;
                    nativeProcessStartupInfo.workingDirectory = tomcatHomeDir.resolvePath("bin");
                    var processArgs:Vector.<String> = new Vector.<String>();
                    processArgs[0] = "-Dcatalina.home="+tomcatHomeDir.nativePath;
                    processArgs[1] = "-classpath";
                    processArgs[2] = tomcatHomeDir.resolvePath("bin/bootstrap.jar").nativePath;
                    processArgs[3] = "org.apache.catalina.startup.Bootstrap";
                    processArgs[4] = arg;
                    nativeProcessStartupInfo.arguments = processArgs;
                    startTomcatProcess = new NativeProcess();
                    startTomcatProcess.start(nativeProcessStartupInfo);
                    startTomcatProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,
                        outputDataHandler);
                    startTomcatProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,
                        errorOutputDataHandler);
                }
                catch (e:Error)
                {
                    Alert.show(e.message, "Error");
                }
            }
 
            public function outputDataHandler(event:ProgressEvent):void
            {
                var process:NativeProcess = event.target as NativeProcess;
                var data:String = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
                log.text += data;
            }
 
            public function errorOutputDataHandler(event:ProgressEvent):void
            {
                var process:NativeProcess = event.target as NativeProcess;
                var data:String = process.standardError.readUTFBytes(startTomcatProcess.standardError.bytesAvailable);
                log.text += data;
            }
 
            private function readConfig():XML
            {
                var file:File = File.applicationStorageDirectory.resolvePath("config.xml");
                if (file.exists)
                {
                    var fileStream:FileStream = new FileStream();
                    fileStream.open(file, FileMode.READ);
                    var xml:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
                    fileStream.close();
                    return xml;
                }
                else
                {
                    return null;
                }
            }
 
            private function writeConfig():void
            {
                var xml:String = '<?xml version="1.0" encoding="utf-8"?>' + File.lineEnding;
                xml += "<config>" + File.lineEnding;
                xml += "<javaHome>" + javaHome.text + "</javaHome>" + File.lineEnding;
                xml += "<tomcatHome>" + tomcatHome.text + "</tomcatHome>" + File.lineEnding;
                xml += "</config>" + File.lineEnding;
 
                var file:File = File.applicationStorageDirectory.resolvePath("config.xml");
                var fileStream:FileStream = new FileStream();
                fileStream.open(file, FileMode.WRITE);
                fileStream.writeUTFBytes(xml);
                fileStream.close();
            }
 
 
        ]]>
    </mx:Script>
 
<mx:RemoteObject id="srv" destination="contacts" endpoint="http://localhost:8080/messagebroker/amf" />
    <mx:TabNavigator width="100%" height="100%">
        <mx:VBox width="100%" height="100%" label="控制台" paddingLeft="8" paddingRight="8" paddingBottom="8">
 
            <mx:Form width="100%">
                <mx:FormItem label="Java Home" width="100%">
                    <mx:TextInput id="javaHome" width="100%"/>
                </mx:FormItem>
                <mx:FormItem label="Tomcat Home (嵌入的TOMCAT)" width="100%">
                    <mx:TextInput id="tomcatHome" width="100%" enabled="false"/>
                </mx:FormItem>
            </mx:Form>
 
            <mx:HBox>
                <mx:Button label="启动" click="startTomcat()"/>
                <mx:Button label="停止" click="stopTomcat()"/>
                <mx:Button label="清除信息" click="log.text=''"/>
 
            </mx:HBox>
            <mx:TextArea id="log" width="100%" height="100%"/>
 
        </mx:VBox>
 
        <mx:VBox label="嵌入的JSP实例" paddingLeft="8" paddingRight="8" paddingBottom="8">
            <mx:HTML id="html" width="100%" height="100%"/>
            <mx:Button label="读取JSP" click="html.location='http://localhost:8080'"/>
        </mx:VBox>
 
        <mx:VBox label="嵌入的RemoteObject实例" paddingLeft="8" paddingRight="8" paddingBottom="8">
            <mx:DataGrid width="100%" height="100%" dataProvider="{srv.findAll.lastResult}">
                <mx:columns>
                    <mx:DataGridColumn dataField="id" headerText="Id"/>
                    <mx:DataGridColumn dataField="firstName" headerText="First Name"/>
                    <mx:DataGridColumn dataField="lastName" headerText="Last Name"/>
                    <mx:DataGridColumn dataField="city" headerText="City"/>
                </mx:columns>
            </mx:DataGrid>
            <mx:Button label="获取数据" click="srv.findAll()"/>
        </mx:VBox>
 
    </mx:TabNavigator>
</mx:WindowedApplication>

下载


源代码: AIRAppWithEmbeddedTomcat.zip (216)

windows demo: AIRAppWithEmbeddedTomcat.exe (173)

Mac Demo: AIRAppWithEmbeddedTomcat.dmg (118)

4 Comments

  1. win-7 says
  2. Edison says

    可以用另一个process做苦力了!

    Reply

  3. 谷哥QQ says

    NativeProcess 实例

    Reply

Leave a Reply

Leave a Reply
  • (required)
  • (required) (will not be published)