摘自: 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
-
common
-
Dfile
=
flex
-
messaging
-
common.jar
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属性"
1
<?
xml version
=
"
1.0
"
encoding
=
"
UTF-8
"
?>
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
1
<
context
-
param
>
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文件,关键点见红色
1
<?
xml version
=
"
1.0
"
encoding
=
"
UTF-8
"
?>
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文件内容,红色字体为关键内容
1
<?
xml version
=
"
1.0
"
encoding
=
"
UTF-8
"
?>
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服务端 关键点红色字体
1
package
com.lx.love.web;
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值
1
<
s:RemoteObject id
=
"
remoteObject
"
destination
=
"
flexUserController
"
fault
=
"
remoteobject1_faultHandler(event)
"
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服务端
1
package
com.lottery.ssc
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客户端调用方式:
1
var user:User
=
new
User();
2
user.password
=
'
123456
'
;
3
user.userName
=
'
lx
'
;
4
user.realName
=
'
liuguly
'
;
5
remoteObject.register(user);
若java服务端返回一个对象,flex客户端调用方式:打印userName
1
protected
function getStringResultHandler(event:ResultEvent):
void
{
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格式的二进制压缩流
POST
/
iloveu
/
messagebroker
/
amf HTTP
/
1.1
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