JDK1.6,设置好环境变量。
Tomcat 6.0。
去官方下载MyEclipse 8.6。下载完毕,那么鬼难用!
首先是没有软件更新,解决办法是:在myeclipse中点Windows-->Preferences
在弹出的对话框的左侧栏,点General-->点Capabilities,然后把Classic Update前的框选上;其次是对于Flash Builder的网页模版js报错,解决方法是:在window--preferences--MyEclipse--Validation然后把JavaScript Validator这一项的Manual 和 Build的勾去掉。
设置一下Tomcat。
去官方网站下载Flash Builder 4.0插件版以及BlazeDS。安装前者以及解压后者。
下载MySQL以及GUI(本人比较懒)和jdbc的jar包。
Spring和Hibernate均使用MyEclipse内置即可。
为了可以调试,还必须下载调试版的Flash player.
现在开始我们的整合之旅。
我们将会写一个登录验证的例子。我们遵循从底层到上层的开发模式,由数据库开始。打开MySQL的GUI工具,创建一个叫做MyFlexDB的数据库。再创建一个叫做“User”的表,表的字段包含了id,username,password三个字段,其中id为自增并且为表主键。脚本如下:
CREATE TABLE `myflexdb`.`User` (
`id` INTEGER NOT NULL DEFAULT NULL AUTO_INCREMENT,
`username` VARCHAR(45),
`password` VARCHAR(45),
PRIMARY KEY (`id`)
)
ENGINE = InnoDB;
接着,我们创建一个Flex工程,名字叫做MyFlex。截屏如下:
输出配置信息,上下文根目录和内容文件夹如下:
令人很不爽的是context竟然不可以修改,真的不爽,搞到得硬编码指定endpoint值。点击next,看到
最后点击finish.
在服务端编写一个测试类Test,在客户端进行调用,配置remoting-config.xml(位于WEB-INF文件夹下面的Flex文件夹)。
Test类如下:
/**
* @author huangjixin
*
*/
public class Test {
public String testStr() {
return "hello,huangjixin";
}
}
配置文件修改成为:
<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">
<adapters>
<adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
</adapters>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
<destination id="Test">
<properties>
<source>Test</source>
</properties>
</destination>
</service>
默认使用my-amf通道即可。
前端主程序文件如下:
<?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" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
protected function testBtn_clickHandler(event:MouseEvent):void
{
Test.testStr();
}
protected function Test_resultHandler(event:ResultEvent):void
{
Alert.show(event.result.toString());
}
protected function Test_faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString());
}
]]>
</fx:Script>
<fx:Declarations>
<s:RemoteObject id="Test"
destination="Test"
showBusyCursor="true"
result="Test_resultHandler(event)"
fault="Test_faultHandler(event)">
</s:RemoteObject>
</fx:Declarations>
<s:Button id="testBtn"
label="测试调用服务端Test类"
click="testBtn_clickHandler(event)"/>
</s:Application>
用MyEclipse部署一下,启动服务器。
允许之后我们可以看到这样的画面:
点击按钮可以看到界面报错了,如下图:
原因是上下文错误。我们必须显式地指出endpoint的值。修改一下主文件,在远程类里面加上: endpoint='http://127.0.0.1:8080/MyFlex/messagebroker/amf'
再次运行可以看到:
接下来测试一下调试环境,使用调试的方式运行程序。
就是喜欢MyEclipse这种简单的调试环境。调试也成功了。
到此我们开始进入第二阶段的整合。
首先为工程加入Spring的jar包。如图所示,一般也别管什么东西了就一股脑加上吧。
点击next可以看到
此处主要是让用户是否对工程加入AOP支持和新建上下文配置文件的目录。
打开Hibernate的视图,新建数据库链接。
新建此链接等下我们在加入Hibernate支持的时候会使用到。
此处我们使用Spring来管理Hibernate链接。
此时Spring的上下文配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/myflexdb">
</property>
<property name="username" value="root"></property>
<property name="password" value="888888"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
</props>
</property>
</bean>
</beans>
新建三个包:com.myflex.model,com.myflex.service, com.myflex.dao
接下来我们做数据库映射,从数据库生成VO,dao。打开Hibernate视图。映射生成结果如图:
将dao文件拖拽到另外一个包中。
系统自动更新配置文件和引用位置。
我们做一下测试,顺便加几条数据到数据库当中。修改前面的Test类如下:
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.myflex.dao.UserDAO;
import com.myflex.model.User;
/**
*
*/
/**
* @author huangjixin
*
*/
public class Test {
public String testStr() {
return "hello,huangjixin";
}
public static void main(String[] args) {
User user=new User();
user.setUsername("huangjixin");
user.setPassword("123456");
//使用上下文获得dao对象;
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDao=(UserDAO)context.getBean("UserDAO");
userDao.save(user);
//查找输出数据库对象
List<User> list=userDao.findAll();
for (User user2 : list) {
System.out.println(user2.getId()+" "+user2.getUsername()+" "+user2.getPassword());
}
}
}
运行之后可以看到:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
1 huangjixin 123456
2 huangjixin 123456
接下来我们进入第三阶段,配置web.xml.主要是配置日志文件,Spring启动侦听器等。配置完毕后它的文件内容如下:
<?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>MyFlex</display-name>
<context-param>
<param-name>flex.class.path</param-name>
<param-value>/WEB-INF/flex/hotfixes,/WEB-INF/flex/jars</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webApp.root</param-value>
</context-param>
<!-- Http Flex Session attribute and binding listener support -->
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!-- MessageBroker Servlet -->
<servlet>
<servlet-name>MessageBrokerServlet</servlet-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>
<init-param>
<param-name>flex.write.path</param-name>
<param-value>/WEB-INF/flex</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>
<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>/MyFlex.html</welcome-file>
</welcome-file-list>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<!-- for WebSphere deployment, please uncomment
<resource-ref>
<description>Flex Messaging WorkManager</description>
<res-ref-name>wm/MessagingWorkManager</res-ref-name>
<res-type>com.ibm.websphere.asynchbeans.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref
-->
</web-app>
接下来我们增加一个工程类以及修改配置文件:
在服务端增加一个工程类,代码如下:
package com.myflex.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import flex.messaging.FactoryInstance;
import flex.messaging.FlexFactory;
import flex.messaging.config.ConfigMap;
import flex.messaging.services.ServiceException;
/**
* This interface is implemented by factory components which provide
* instances to the flex messaging framework. To configure flex data services
* to use this factory, add the following lines to your services-config.xml
* file (located in the WEB-INF/flex directory of your web application).
*
* <factories>
* <factory id="spring" class="flex.samples.factories.SpringFactory" />
* </factories>
*
* You also must configure the web application to use spring and must copy the spring.jar
* file into your WEB-INF/lib directory. To configure your app server to use spring,
* you add the following lines to your WEB-INF/web.xml file:
*
* <context-param>
* <param-name>contextConfigLocation</param-name>
* <param-value>/WEB-INF/applicationContext.xml</param-value>
* </context-param>
*
* <listener>
* <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
* </listener>
*
* Then you put your spring bean configuration in WEB-INF/applicationContext.xml (as per the
* line above). For example:
*
* <?xml version="1.0" encoding="UTF-8"?>
* <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
*
* <beans>
* <bean name="weatherBean" class="dev.weather.WeatherService" singleton="true"/>
* </beans>
*
* Now you are ready to define a destination in flex that maps to this existing service.
* To do this you'd add this to your WEB-INF/flex/remoting-config.xml:
*
* <destination id="WeatherService">
* <properties>
* <factory>spring</factory>
* <source>weatherBean</source>
* </properties>
* </destination>
*
* @author Jeff Vroom
*/
public class SpringFactory implements FlexFactory
{
private static final String SOURCE = "source";
/**
* This method can be used to initialize the factory itself. It is called with configuration
* parameters from the factory tag which defines the id of the factory.
*/
public void initialize(String id, ConfigMap configMap) {}
/**
* This method is called when we initialize the definition of an instance
* which will be looked up by this factory. It should validate that
* the properties supplied are valid to define an instance.
* Any valid properties used for this configuration must be accessed to
* avoid warnings about unused configuration elements. If your factory
* is only used for application scoped components, this method can simply
* return a factory instance which delegates the creation of the component
* to the FactoryInstance's lookup method.
*/
public FactoryInstance createFactoryInstance(String id, ConfigMap properties)
{
SpringFactoryInstance instance = new SpringFactoryInstance(this, id, properties);
instance.setSource(properties.getPropertyAsString(SOURCE, instance.getId()));
return instance;
} // end method createFactoryInstance()
/**
* Returns the instance specified by the source
* and properties arguments. For the factory, this may mean
* constructing a new instance, optionally registering it in some other
* name space such as the session or JNDI, and then returning it
* or it may mean creating a new instance and returning it.
* This method is called for each request to operate on the
* given item by the system so it should be relatively efficient.
* <p>
* If your factory does not support the scope property, it
* report an error if scope is supplied in the properties
* for this instance.
*/
public Object lookup(FactoryInstance inst)
{
SpringFactoryInstance factoryInstance = (SpringFactoryInstance) inst;
return factoryInstance.lookup();
}
static class SpringFactoryInstance extends FactoryInstance
{
SpringFactoryInstance(SpringFactory factory, String id, ConfigMap properties)
{
super(factory, id, properties);
}
public String toString()
{
return "SpringFactory instance for id=" + getId() + " source=" + getSource() + " scope=" + getScope();
}
public Object lookup()
{
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(flex.messaging.FlexContext.getServletConfig().getServletContext());
String beanName = getSource();
try
{
return appContext.getBean(beanName);
}
catch (NoSuchBeanDefinitionException nexc)
{
ServiceException e = new ServiceException();
String msg = "Spring service named '" + beanName + "' does not exist.";
e.setMessage(msg);
e.setRootCause(nexc);
e.setDetails(msg);
e.setCode("Server.Processing");
throw e;
}
catch (BeansException bexc)
{
ServiceException e = new ServiceException();
String msg = "Unable to create Spring service named '" + beanName + "' ";
e.setMessage(msg);
e.setRootCause(bexc);
e.setDetails(msg);
e.setCode("Server.Processing");
throw e;
}
}
}
}
在services-config.xml文件当中增加如下标签:
<factories>
<factory id="springFactory" class="com.myflex.factory.SpringFactory"/>
</factories>
在remoting-config.xml文件当中增加:
<destination id="UserDAO">
<properties>
<factory>springFactory</factory>
<source>UserDAO</source>
</properties>
</destination>
修改主文件:
<?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"
minWidth="955" minHeight="600"
pageTitle="MyFlex">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
protected function testBtn_clickHandler(event:MouseEvent):void
{
userDao.findAll();
}
protected function Test_resultHandler(event:ResultEvent):void
{
Alert.show(event.result.toString());
}
protected function Test_faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString());
}
]]>
</fx:Script>
<fx:Declarations>
<s:RemoteObject id="userDao"
destination="UserDAO"
showBusyCursor="true"
result="Test_resultHandler(event)"
fault="Test_faultHandler(event)"
endpoint="http://127.0.0.1:8080/MyFlex/messagebroker/amf">
</s:RemoteObject>
</fx:Declarations>
<s:Button id="testBtn"
label="测试调用服务端Test类"
click="testBtn_clickHandler(event)"
horizontalCenter="0"
verticalCenter="0"/>
</s:Application>
最后阶段了,就是为DAO加入事务能力。
<!-- 定义事务管理器(声明式的事务) -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="UserDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass" value="true" />
<property name="transactionManager" ref="myTransactionManager" />
<property name="target" ref="UserDAO" />
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>