首页 > 代码库 > 基于restful注解(spring4.0.2整合flex+blazeds+spring-mvc)<一>

基于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-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="http://www.mamicode.com/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