flex+blazeds+调用Java
本文讲解flex 怎么去调用 java 代码,这使我折腾了大半天,主要在一个问题上 。
关于blazeds 的讲解,去网上搜一下,一大把对它的解释,在此不做介绍。
1.首先下载 blazeds.war ,在下面提供下载 ,解压把它下面的WEB-INF\lib下所有的.jar copy 到你的flex web项目下WEB-INF 中的lib 中 。
2. 把 blazed 下的WEB-INF\flex ,这个文件夹连同所有的文件都copy到你的项目下的WEB-INF中。
3. 把 blazed 下的 WEB-INF\web.xml 中的配置copy 到你的项目中的web.xml 中去 。
我的web.xml如下
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!-- 必须修改,最好与项目同名 --> <display-name>flexTest005</display-name> <description>BlazeDS Application</description> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/conf/spring.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring 刷新Introspector防止内存泄露 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <servlet> <servlet-name>DruidStatView</servlet-name> <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DruidStatView</servlet-name> <url-pattern>/durid/*</url-pattern> </servlet-mapping> <!-- Http Flex Session attribute and binding listener support --> <listener> <listener-class>flex.messaging.HttpFlexSession</listener-class> </listener> <!-- MessageBroker Servlet --> <servlet> <servlet-name>MessageBrokerServlet</servlet-name> <!-- <display-name>MessageBrokerServlet</display-name> --> <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class> <init-param> <param-name>services.configuration.file</param-name> <param-value>/WEB-INF/flex/services-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>MessageBrokerServlet</servlet-name> <url-pattern>/messagebroker/*</url-pattern> </servlet-mapping> <!-- INIT --> <servlet> <servlet-name>InitSpring</servlet-name> <servlet-class>oss.com.ressapp.spring.servlet.InitSpringServlet</servlet-class> <load-on-startup>10</load-on-startup> </servlet> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
4. 在此要注意一个问题,如果是flex 的web项目的话,在新建flex web 项目时,最好把输出文件夹改为你WEB的根目录下,如WEBROOT , WebContent 当打成一个war包中,它就在根目录下,如果你用WEBROOT\flexview 或 WEBContent\... , 也就是在Web根目录下加了一个子目录的话,后面调用java 会报错,即使改了service-config.xml 后,也还会报错。 如果刚开始建错了,后面也可以改,在项目上右键属性中也可以改的,如图:
4,在上图中编译时,如果把找不到ViewString,则需加入参数,如图:
参数为: -locale zh_CN -source-path=locale/{locale} -keep-all-type-selectors=true
5, 现在可以写一个java类了:
package oss.com.flex.action; import oss.com.ressapp.spring.util.BeanUtil; /** * 相当于请求的Controller ,这个是不受spring 管理,事务都要配在service 层中即可 * @author lihc * */ public class FlexJavaAction { /** * 每个被flex 调用的类,必须要一个无参的构造方法或不写造构方法 */ public FlexJavaAction() { } // 得到service private TestService ts = BeanUtil.getBeanByClassName("tservice" , TestService.class) ; public String getTest1(String str) { System.out.println(" FlexJavaAction test1 : " + str ); return ts.getString(str) ; } }
说明,这个类不受spring管理了, 如何得到spring中受管理的类,就要自已写一个Servlet 把servletContext 传给 WebApplicationContextUtils ,从而得到ApplicationContext, 再去得spring中受管理的类:
Servlet如:
package oss.com.ressapp.spring.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import oss.com.ressapp.spring.util.BeanUtil; import oss.com.ressapp.spring.util.SpringDictionary; public class InitSpringServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; public void init() throws ServletException { SpringDictionary.GLOBAL_REALPATH = this.getServletContext().getRealPath("/"); BeanUtil.servletContext = this.getServletContext(); System.out.println("Init Spring Start!"); System.out.println("servletContext is : " + BeanUtil.servletContext); BeanUtil.initSpring(); System.out.println("Init Spring OK!"); } }
BeanUtil如:
package oss.com.ressapp.spring.util; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; public class BeanUtil { private static final Log log = LogFactory.getLog(BeanUtil.class); public static ServletContext servletContext; private static ApplicationContext applicationContext = null; public static void initSpring(){ applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); } public static Object getBeanByClassName(String _className) { if(applicationContext==null ){ log.debug("ctx is null"); initSpring(); } String lowclassName = _className.substring(0, 1).toLowerCase() + _className.substring(1, _className.length()); log.info("get IoC ClassName: " + lowclassName); return applicationContext.getBean(lowclassName); } public static <T> T getBeanByClassName(String _className, Class<T> claz) { if(applicationContext==null ){ log.debug("ctx is null"); initSpring(); } log.info("get IoC ClassName: " + _className); return applicationContext.getBean(_className, claz) ; } }
然后在Spring 中注册,在你需要的地方通过以下去得到spring的受管类:
private TestService ts = BeanUtil.getBeanByClassName("tservice" , TestService.class) ;
6. 以上是Java这一侧写完了,再写Flex ,在写在,先把上面写的flexjavaAction,注册到 blazds中,才能让flex 通过它去调用java
在文件:WEB-INF\flex\remoting-config.xml 中,注册为:
<destination id="flexJavaAction"> <properties> <source>oss.com.flex.action.FlexJavaAction</source> </properties> </destination>
7. 再写一个flex 主页面来测试:
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:supportClasses="com.esri.ags.skins.supportClasses.*" minWidth="955" minHeight="600" initialize="init()"> <fx:Script> <![CDATA[ import mx.controls.Alert; import mx.rpc.AbstractOperation; import mx.rpc.events.ResultEvent; import mx.rpc.remoting.RemoteObject; import org.com.oss.flex.util.UtilCommon; private var ro_:RemoteObject ; private function init():void { Alert.show("init..."); } private function onCallJavaPro():void { ro_ = UtilCommon.getServerAction("flexJavaAction"); var abstractOperation : AbstractOperation = ro_.getOperation("getTest1") ; abstractOperation.addEventListener(ResultEvent.RESULT, getResultHandle); ro_.getTest1("flex call "); // 调用方法,或以传入参数 } private function getResultHandle(evt:ResultEvent):void { //Alert.show("evt is : " + evt ); var result :String = evt.result as String ; Alert.show("result is : " + result ) ; } ]]> </fx:Script> <mx:ViewStack width="100%" height="100%"> <mx:HBox width="100%"> <s:Button label="flex调用java程序" width="60" click="onCallJavaPro()"/> </mx:HBox> </mx:ViewStack> </s:Application>
在这里,可以通过<s:RemoteObject /> 去调用,但我习惯写个方法,用as 脚本去调用,主要为:
ro_ = UtilCommon.getServerAction("flexJavaAction"); var abstractOperation : AbstractOperation = ro_.getOperation("getTest1") ; abstractOperation.addEventListener(ResultEvent.RESULT, getResultHandle); ro_.getTest1("flex call "); // 调用方法,或以传入参数
public static function getServerAction(_destination : String):RemoteObject { var ro:RemoteObject; ro = new RemoteObject(); ro.destination = _destination; ro.endpoint = "messagebroker/amf"; ro.addEventListener( FaultEvent.FAULT, doFaultHandle ); return ro; } private static function doFaultHandle(event:FaultEvent):void { Alert.show(event.fault.toString()); trace(event.message); }
8 ,写完,启动tomcat就可以了调用了。
9, 如果你没成功,会得到以下错误提示,
这样,你就要去,检查web.xml ,检查blazed的包是否加入,最后重点看下上面这个请求的地址,它是要在从web的根目录起的,所以你所有的flex编译输出文件必须为WEB的根目录:这个只是从界面上报的,后台没有报错。
在调试时,在后面会得到:
警告: 等待 socket 策略文件时在 xmlsocket://localhost:27813 上超时(3 秒钟)。这不会造成任何问题,但可访问 http://www.adobe.com/go/strict_policy_files_cn 以获得说明。
错误: 来自 http://localhost:8080/flexTest005/flexviewer/flexjavaTest.swf 的 SWF 不能不使用策略文件便连接到自己的域中的 socket。请访问 http://www.adobe.com/go/strict_policy_files_cn 以解决此问题。
*** 安全沙箱冲突 ***
到 localhost:27813 的连接已停止 - 不允许从 http://localhost:8080/flexTest005/flexviewer/flexjavaTest.swf 进行连接
如这样的信息, 和上面一样去检查。
10 .本人也试去修改service-config.xml 下的请求地址,也不起作用,此文件中内容为:
<?xml version="1.0" encoding="UTF-8"?> <services-config> <services> <service-include file-path="remoting-config.xml" /> <service-include file-path="proxy-config.xml" /> <service-include file-path="messaging-config.xml" /> </services> <security> <login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/> <!-- Uncomment the correct app server <login-command class="flex.messaging.security.TomcatLoginCommand" server="JBoss"> <login-command class="flex.messaging.security.JRunLoginCommand" server="JRun"/> <login-command class="flex.messaging.security.WeblogicLoginCommand" server="Weblogic"/> <login-command class="flex.messaging.security.WebSphereLoginCommand" server="WebSphere"/> --> <!-- <security-constraint id="basic-read-access"> <auth-method>Basic</auth-method> <roles> <role>guests</role> <role>accountants</role> <role>employees</role> <role>managers</role> </roles> </security-constraint> --> </security> <channels> <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> <channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel"> <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/> <properties> <add-no-cache-headers>false</add-no-cache-headers> </properties> </channel-definition> <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/> <properties> <polling-enabled>true</polling-enabled> <polling-interval-seconds>4</polling-interval-seconds> </properties> </channel-definition> <!-- <channel-definition id="my-http" class="mx.messaging.channels.HTTPChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/http" class="flex.messaging.endpoints.HTTPEndpoint"/> </channel-definition> <channel-definition id="my-secure-http" class="mx.messaging.channels.SecureHTTPChannel"> <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/httpsecure" class="flex.messaging.endpoints.SecureHTTPEndpoint"/> <properties> <add-no-cache-headers>false</add-no-cache-headers> </properties> </channel-definition> --> </channels> <logging> <target class="flex.messaging.log.ConsoleTarget" level="Error"> <properties> <prefix>[BlazeDS] </prefix> <includeDate>false</includeDate> <includeTime>false</includeTime> <includeLevel>false</includeLevel> <includeCategory>false</includeCategory> </properties> <filters> <pattern>Endpoint.*</pattern> <pattern>Service.*</pattern> <pattern>Configuration</pattern> </filters> </target> </logging> <system> <redeploy> <enabled>false</enabled> <!-- <watch-interval>20</watch-interval> <watch-file>{context.root}/WEB-INF/flex/services-config.xml</watch-file> <watch-file>{context.root}/WEB-INF/flex/proxy-config.xml</watch-file> <watch-file>{context.root}/WEB-INF/flex/remoting-config.xml</watch-file> <watch-file>{context.root}/WEB-INF/flex/messaging-config.xml</watch-file> <watch-file>{context.root}/WEB-INF/flex/data-management-config.xml</watch-file> <touch-file>{context.root}/WEB-INF/web.xml</touch-file> --> </redeploy> </system> </services-config>
它有很多的endpoint <endpoint url=http://{server.name}:{server.port}/{context.root}/messagebroker/http
我在{context.roog}/flexview/messagebooker/http....
也调用不到。
本人也没查找这些 {server.port} {context.root } 是从哪里来的,但在配web.xml中有一个flex.messaging.MessageBrokerServlet ,猜想是从这里来的吧,如有知道的请告知下。
11,通上blazed方法调用,还有别的方式去调用java,如webservice,自已写socket,等,以后有时间再研究下。继续学习中 。