基于restful注解(spring4.0.2整合flex+blazeds+spring-mvc)
摘自: 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.jarmvn install:install
–file –Dpackaging=jar –DgroupId=com.adobe.blazeds –Dversion=4.0.0.14931 –DartifactId=blazeds–opt –Dfile=flex–messaging–opt.jarmvn install:install
–file –Dpackaging=jar –DgroupId=com.adobe.blazeds –Dversion=4.0.0.14931 –DartifactId=blazeds–proxy –Dfile=flex–messaging–proxy.jarmvn 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