摘自: http://www.blogjava.net/liuguly/archive/2014/03/10/410824.html
参考官网:
1.http://livedocs.adobe.com/blazeds/1/blazeds_devguide/
2.http://docs.spring.io/spring-flex/docs/1.5.2.RELEASE/reference/html/
1)下载blazeds(turnkey4.0.x版本)网址:http://sourceforge.net/adobe/blazeds/wiki/Home/
2)先创建maven工程,然后进入blazeds目录/tomcat/webapps/blazeds/WEB-INF/flex 连flex目录拷贝到src/main/resource目录下(也可以直接拷贝文件)
如图:
3)核心flex相关jar包
下载spring-flex-core-1.5.2.RELEASE.jar
blazeds-core-4.0.0.14931.jar
blazeds-common-4.0.0.14931.jar
blazeds-proxy-4.0.0.14931.jar
blazeds-remoting-4.0.0.14931.jar
其中spring-flex-core-1.5.2.RELEASE.jar可以从远程maven中心仓库下载,而blazeds的jar在中心仓库版本有误,如图:
spring容器启动时spring-flex-core-1.5.2依赖的是
blazeds的4.0.0.14931版本,而maven中心仓库并无此jar包,因此以上四个包需手工打入本地maven仓库,打入命令
进入blazeds目录/resources/lib下执行以下maven命令
mvn install:install-file -Dpackaging=jar -DgroupId=com.adobe.blazeds -Dversion=4.0.0.14931 -DartifactId=blazeds-core -Dfile=flex-messaging-core.jar
mvn install:install-file -Dpackaging=jar -DgroupId=com.adobe.blazeds -Dversion=4.0.0.14931 -DartifactId=blazeds-opt -Dfile=flex-messaging-opt.jar
mvn install:install-file -Dpackaging=jar -DgroupId=com.adobe.blazeds -Dversion=4.0.0.14931 -DartifactId=blazeds-proxy -Dfile=flex-messaging-proxy.jar
mvn install:install-file -Dpackaging=jar -DgroupId=com.adobe.blazeds -Dversion=4.0.0.14931 -DartifactId=blazeds-remoting -Dfile=flex-messaging-remoting.jar
至此在工程中即可引入相关jar包.
4) 配置flex/services-config.xml文件 红色为修改后内容
channel对于flex来讲,相当于一个通信管道,在flex客户端端表现为endpoint="下面红色字体中endpoint.url属性"
2 <services-config>
3
4 <services>
5 <service-include file-path="remoting-config.xml" />
6 <service-include file-path="proxy-config.xml" />
7 <service-include file-path="messaging-config.xml" />
8 </services>
9
10 <security>
11 <login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
12 <!-- Uncomment the correct app server
13 <login-command class="flex.messaging.security.TomcatLoginCommand" server="JBoss">
14 <login-command class="flex.messaging.security.JRunLoginCommand" server="JRun"/>
15 <login-command class="flex.messaging.security.WeblogicLoginCommand" server="Weblogic"/>
16 <login-command class="flex.messaging.security.WebSphereLoginCommand" server="WebSphere"/>
17 -->
18
19 <!--
20 <security-constraint id="basic-read-access">
21 <auth-method>Basic</auth-method>
22 <roles>
23 <role>guests</role>
24 <role>accountants</role>
25 <role>employees</role>
26 <role>managers</role>
27 </roles>
28 </security-constraint>
29 -->
30 </security>
31
32 <channels>
33
34 <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
35 <endpoint url="http://localhost:8080/iloveu/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
36 <properties>
37 <polling-enabled>false</polling-enabled>
38 </properties>
39 </channel-definition>
40
41 <channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
42 <endpoint url="https://localhost:8080/iloveu/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
43 <properties>
44 <add-no-cache-headers>false</add-no-cache-headers>
45 </properties>
46 </channel-definition>
47
48 <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
49 <endpoint url="http://localhost:8080/iloveu/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
50 <properties>
51 <polling-enabled>true</polling-enabled>
52 <polling-interval-seconds>4</polling-interval-seconds>
53 </properties>
54 </channel-definition>
55
56 <!--
57 <channel-definition id="my-http" class="mx.messaging.channels.HTTPChannel">
58 <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/http" class="flex.messaging.endpoints.HTTPEndpoint"/>
59 </channel-definition>
60
61 <channel-definition id="my-secure-http" class="mx.messaging.channels.SecureHTTPChannel">
62 <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/httpsecure" class="flex.messaging.endpoints.SecureHTTPEndpoint"/>
63 <properties>
64 <add-no-cache-headers>false</add-no-cache-headers>
65 </properties>
66 </channel-definition>
67 -->
68 </channels>
69
70 <logging>
71 <target class="flex.messaging.log.ConsoleTarget" level="Error">
72 <properties>
73 <prefix>[BlazeDS] </prefix>
74 <includeDate>false</includeDate>
75 <includeTime>false</includeTime>
76 <includeLevel>false</includeLevel>
77 <includeCategory>false</includeCategory>
78 </properties>
79 <filters>
80 <pattern>Endpoint.*</pattern>
81 <pattern>Service.*</pattern>
82 <pattern>Configuration</pattern>
83 </filters>
84 </target>
85 </logging>
86
87 <system>
88 <redeploy>
89 <enabled>false</enabled>
90 <!--
91 <watch-interval>20</watch-interval>
92 <watch-file>{context.root}/WEB-INF/flex/services-config.xml</watch-file>
93 <watch-file>{context.root}/WEB-INF/flex/proxy-config.xml</watch-file>
94 <watch-file>{context.root}/WEB-INF/flex/remoting-config.xml</watch-file>
95 <watch-file>{context.root}/WEB-INF/flex/messaging-config.xml</watch-file>
96 <watch-file>{context.root}/WEB-INF/flex/data-management-config.xml</watch-file>
97 <touch-file>{context.root}/WEB-INF/web.xml</touch-file>
98 -->
99 </redeploy>
100 </system>
101
102 </services-config>
103
5)搭建spring-mvc框架 web.xml
2 <param-name>contextConfigLocation</param-name>
3 <param-value>
4 classpath:applicationContext.xml
5 </param-value>
6 </context-param>
7
8 <listener>
9 <listener-class>
10 org.springframework.web.context.ContextLoaderListener
11 </listener-class>
12 </listener>
13
14 <servlet>
15 <servlet-name>spring-mvc</servlet-name>
16 <servlet-class>
17 org.springframework.web.servlet.DispatcherServlet
18 </servlet-class>
19 <init-param>
20 <param-name>contextConfigLocation</param-name>
21 <param-value>classpath:spring-mvc-servlet.xml</param-value>
22 </init-param>
23 <load-on-startup>1</load-on-startup>
24 </servlet>
25
26 <servlet-mapping>
27 <servlet-name>spring-mvc</servlet-name>
28 <url-pattern>*.htm</url-pattern>
29 </servlet-mapping>
30
31 <servlet>
32 <servlet-name>flex</servlet-name>
33 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
34 <init-param>
35 <param-name>contextConfigLocation</param-name>
36 <param-value>classpath:flex-servlet.xml</param-value>
37 </init-param>
38 <load-on-startup>1</load-on-startup>
39 </servlet>
40
41 <servlet-mapping>
42 <servlet-name>flex</servlet-name>
43 <url-pattern>/messagebroker/amf/*</url-pattern>
44 </servlet-mapping>
因为基于maven工程,配置文件都在src/main/resources目录下,flex和spring-mvc子容器单独配置classpath,否则会自动查找/WEB-INF/<servlet-name>-servlet.xml文件。
6)贴上applicationContext.xml文件,关键点见红色
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:p="http://www.springframework.org/schema/p"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xmlns:util="http://www.springframework.org/schema/util"
7 xmlns:mvc="http://www.springframework.org/schema/mvc"
8 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
9 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
10 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
11 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
12
13 <import resource="flex-context.xml"/>
14
15 <!-- 自动扫描且只扫描@Controller -->
16 <context:component-scan base-package="com.lx.love.web" use-default-filters="false">
17 <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
18 <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
19 </context:component-scan>
20
21 <mvc:annotation-driven>
22 <mvc:message-converters register-defaults="true">
23 <bean class="org.springframework.flex.http.AmfHttpMessageConverter"/>
24 </mvc:message-converters>
25 </mvc:annotation-driven>
26
27
28 <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
29 <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
30 <property name="defaultViews">
31 <list>
32 <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
33 <bean class="org.springframework.flex.http.AmfView"/>
34 </list>
35 </property>
36 </bean>
37
38 <bean id= "contentNegotiationManager" class= "org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
39 <!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
40 <property name= "favorPathExtension" value= "true" />
41 <!-- 用于开启 /userinfo/123?format=json 的支持 -->
42 <property name= "favorParameter" value= "true" />
43 <property name= "parameterName" value= "format"/>
44 <!-- 是否忽略Accept Header -->
45 <property name= "ignoreAcceptHeader" value= "false"/>
46 <property name= "mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 -->
47 <map>
48 <entry key="json" value="application/json"/>
49 <entry key="xml" value="application/xml"/>
50 <entry key="amf" value="application/x-amf"/>
51 </map>
52 </property>
53 <!-- 默认的content type -->
54 <property name= "defaultContentType" value= "application/x-amf" />
55 </bean>
56
57 </beans>
关键点:23行定义将flex客户端传递来的AMF格式消息转换为java可识别的内容
28-36以及50行定义amf格式的返回值也即spring-mvc的返回视图根据http协议头的Accept Header来判断amf格式的返回
7) 上面flex-servlet.xml中引入的flex-context.xml文件内容,红色字体为关键内容
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:flex="http://www.springframework.org/schema/flex"
5 xsi:schemaLocation="http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.5.xsd
6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
7
8
9 <bean id="customExceptionTranslator" class="com.lx.love.flex.exception.CustomExceptionTranslator"/>
10 <bean id="destinationCountingConfigProcessor" class="com.lx.love.flex.processor.DestinationCountingConfigProcessor"/>
11 <bean id="flexMessageIntercepter" class="com.lx.love.flex.intercepter.FlexMessageIntercepter"/>
12
13 <flex:message-broker services-config-path="classpath*:/flex/services-config.xml">
14 <flex:exception-translator ref="customExceptionTranslator"/>
15 <flex:config-processor ref="destinationCountingConfigProcessor"/>
16 <flex:message-interceptor before="FIRST" ref="flexMessageIntercepter"/>
17 </flex:message-broker>
18
19 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
20 <property name="properties">
21 <props>
22 <prop key="channel1">my-amf</prop>
23 <prop key="channel2">my-secure-amf,my-amf</prop>
24 </props>
25 </property>
26 </bean>
27
28 <!-- 还可以直接在controller层注解 -->
29 <!-- <bean id="flexController" class="com.lx.love.web.UserController">
30 <flex:remoting-destination />
31 </bean> -->
32
33
34 </beans>
35
里面的关键点为13行配置message-broker在src/main/resources/下找到services-config.xml文件
14-16为可选增强功能,类似拦截器,异常转换为java可识别的异常等
19-26行用于在控制器类上注解@RemotingDestination(value="flexUserController" , channels={"${channel1},${channel2}"})
可选channels使用。至此xml文件配置完毕。
示例:java服务端 关键点红色字体
2
3 import java.io.UnsupportedEncodingException;
4
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.flex.remoting.RemotingDestination;
7 import org.springframework.flex.remoting.RemotingInclude;
8 import org.springframework.http.HttpEntity;
9 import org.springframework.http.HttpHeaders;
10 import org.springframework.http.HttpStatus;
11 import org.springframework.http.MediaType;
12 import org.springframework.http.ResponseEntity;
13 import org.springframework.web.bind.annotation.RequestBody;
14 import org.springframework.web.bind.annotation.RequestMapping;
15 import org.springframework.web.bind.annotation.RequestMethod;
16 import org.springframework.web.bind.annotation.RestController;
17
18 import com.lx.love.dto.User;
19 import com.lx.love.service.UserService;
20
21 @RestController()
22 @RemotingDestination(value="flexUserController" , channels={"${channel1}"})
23 public class FlexUserService {
24
25 @Autowired
26 private UserService userService;
27
28 // @RemotingExclude
29 // @RequestMapping(method=RequestMethod.POST)
30 // public ModelAndView createUser(User user){
31 // userService.createUser(user);
32 // ModelAndView mav = new ModelAndView();
33 // mav.setViewName("/user/createSuccess");
34 // mav.addObject("user",user);
35 // return mav;
36 // }
37
38 @RemotingInclude
39 @RequestMapping(value="/register",method=RequestMethod.POST)
40 public User register(@RequestBody User user){
41 System.out.println("userName="+user.getUserName());
42 System.out.println("1234567");
43 user.setUserName("ztt");
44 user.setRealName("love");
45 user.setPassword("123456");
46 return user;
47 }
48
49 @RemotingInclude
50 @RequestMapping(value="/test",method=RequestMethod.POST)
51 public String testMy(String userName){
52 System.out.println("userName="+userName);
53 return userName;
54 }
55
56 /**
57 * produces -->针对Content-Type 增加一种类型,若不匹配用默认的
58 * consumer -->针对Accept 只能满足指定的内容
59 * @param requestEntity
60 * @return
61 * @throws UnsupportedEncodingException
62 */
63 @RemotingInclude
64 @RequestMapping(value="/handler5" , produces={MediaType.APPLICATION_JSON_VALUE})
65 public ResponseEntity<String> handle5(HttpEntity<byte[]> requestEntity)
66 throws UnsupportedEncodingException{
67 String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader");
68 byte[] requestBody = requestEntity.getBody();
69 HttpHeaders responseHeaders = new HttpHeaders();
70 responseHeaders.set("lxx", "ztt");
71
72 return new ResponseEntity<String>("Hello World"+requestBody,responseHeaders,HttpStatus.CREATED);
73 }
74
75 @RemotingInclude
76 @RequestMapping(value="/handler")
77 public String handler(@RequestBody String requestBody){
78 System.out.println(requestBody);
79 return "/user/success";
80 }
81
82 }
83
@RemotingDestination(value="flexUserController" , channels={"${channel1}"})
其中value值对应flex客户端:destination值
2 endpoint="http://localhost:8081/iloveu/messagebroker/amf" >
3 <s:method name="register" result="getStringResultHandler(event)"/>
4 <s:method name="testMy" result="getStringResultHandler(event)" />
5 </s:RemoteObject>
如果flex客户端传递一个User.as类对象到java服务端
2 {
3 [Bindable]
4 [RemoteClass(alias="com.lx.love.dto.User")]
5 public class User
6 {
7 private var _userName:String;
8 private var _password:String;
9 private var _realName:String;
10
11 public function User()
12 {
13 }
14
15 public function get realName():String
16 {
17 return _realName;
18 }
19
20 public function set realName(value:String):void
21 {
22 _realName = value;
23 }
24
25 public function get password():String
26 {
27 return _password;
28 }
29
30 public function set password(value:String):void
31 {
32 _password = value;
33 }
34
35 public function get userName():String
36 {
37 return _userName;
38 }
39
40 public function set userName(value:String):void
41 {
42 _userName = value;
43 }
44
45 }
46 }
里面get和set方法的属性名要和java服务器的属性名一致,flex客户端调用方式:
2 user.password='123456';
3 user.userName='lx';
4 user.realName='liuguly';
5 remoteObject.register(user);
若java服务端返回一个对象,flex客户端调用方式:打印userName
2 var user:Object = event.result;
3 Alert.show(user.userName);
4 Alert.show(event.result.toString());
5 }
至此,flex客户端和java服务端通信成功,一次完整的http协议请求-响应如下:
flex客户端http请求:以下http消息体出现的鸟文就是amf格式的二进制压缩流
Host: localhost:8081
Accept: */*
Content-Type: application/x-amf
Connection: keep-alive
Cookie: JSESSIONID=ovi35kxlymahlouuqbqzj7h2
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Content-Length: 715