Setting @CODEPAGE explicitly affects literal strings in a single response. Response.CodePage affects dynamic strings in a single response, and Session.CodePage affects dynamic strings in all responses in a session.
这句话解释清楚了@CODEPAGE,Response.CodePage,Session.CodePage 分别的作用是什么。
@CODEPAGE作用于所有静态的字符串,比如某文件中的 const blogname=”我的家”
Response.CodePage,Session.CodePage作用于所有动态输出的字符串,比如<%=blogname%>
这句话很关键的是说明了Response.CodePage的作用范围是a single response,而SXNA中声明的Session.CodePage的作用范围是all responses in a session。
再看另外一句话。
If Response.CodePage is not explicitly set in a page, it is implicitly set by Session.CodePage, if sessions are enabled. If sessions are not enabled, Response.CodePage is set by @CodePage, if @CodePage is present in the page. If there is no @CodePage in the page, Response.CodePage is set by the AspCodePage metabase property. If the AspCodePage metabase property is not set, or set to 0, Response.CodePage is set by the system ANSI code page.
这句话我乍一看,把意思理解成了这样:在sessions are enabled的时候,如果Response.CodePage没有声明,则Response.CodePage会被Session.CodePage赋值。如果sessions are not enabled的时候, 如果@CodePage已声明,则Response.CodePage会被@CodePage赋值,等等………….
这句话 解释了为什么从SXNA中出来以后进入一些别的页面比如oblog,z-blog等等容易出现乱码,因为其他程序没有声明 Response.CodePage而恰巧SXNA声明了Session.CodePage,因此一进入SXNA,Session.CodePage立即被赋值(版本不同,有的版本赋了936有的版本赋了65001),而后进入其他程序的时候Response.CodePage马上被 Session.CodePage赋值,如果这时Response.CodePage与页面本身编码不一样的话,页面就会出现乱码。所以进入z-blog 出现乱码的时候我查了当时的Session.CodePage和Response.CodePage都是936,而进入oblog出现乱码的时候 Session.CodePage和Response.CodePage都是65001.就是说要想保证叶面不出现乱码,应该声明 Response.CodePage,否则他就会按照Session.CodePage来解释网页(而不是按照@codepage解释网页).
如 果仅仅按照上面的解释的话,我实际上是很糊涂的,因为我们都是用的中文操系统,当每一次进入浏览器的时候你可以尝试输出 Session.CodePage,能看到他都是936!为什么进入Z-blog的时候他不把默认的Session.CodePage的936赋给 Response.CodePage呢?反而把@CodePage给了Response.CodePage?什么情况下Session.CodePage 才赋值给Response.CodePage呢?原文的sessions are enabled应该如何理解呢?
也许上面的话应该这样理解:
在Session.CodePage 被任何程序声明的时候,如果Response.CodePage没有声明,则Response.CodePage会被Session.CodePage赋值。如果Session.CodePage没有被任何程序声明的时候, 如果@CodePage已声明,则Response.CodePage会被@CodePage赋值,….,最后的页面动态内容部分按照 Response.CodePage的值解释。
因为Zblog和Oblog都声明了@CodePage,所以,用户刚刚启动完机器然后进入浏览器浏览Zblog和Oblog的时候Response.CodePage会被@CodePage赋值,于是叶面显示正常。
这句话进一步解释了产生乱码的原因
If you set Response.CodePage or Session.CodePage explicitly, do so before sending non-literal strings to the client. If you use literal and non-literal strings in the same page, make sure the code page of @CODEPAGE matches the code page of Response.CodePage, or the literal strings are encoded differently from the non-literal strings and display incorrectly.
其中比较有用的一句话是说如果Response.CodePage和 @CODEPAGE不一样的话会产生乱码。也就是说当Z-blog的@CODEPAGE=65001而Z-blog的Response.CodePage 被Session.CodePage赋为936的时候就会出现乱码,oblog反之亦然。
不知道上面说了这么多解释清楚没有-_-||
下面解释一下为什么SXNA有时会把Session.CodePage赋为936,我有一个版本是这样写的:
<% originalCodePage=Session.CodePage %>
…….
<% Session.CodePage=OriginalCodePage %>
当 用户进入浏览器的时候Session.CodePage默认为936,这个时候的默认936不是程序声明的,因此不会赋给 Response.CodePage,当进入SXNA的时候,Session.CodePage被上面那段代码一折腾就变成了程序声明的 Session.CodePage=936,因此再进入Zblog的时候就把936给了Response.CodePage。
至此,全部原因已经分析清楚了。
因此说,保证asp叶面一定不会出现乱码的代码应该是这样的:(假定是UTF-8的叶子)
<%@ CODEPAGE=65001 %>
<% Response.CodePage=65001%>
<% Response.Charset="UTF-8" %>
进一步说明为什么要加Response.Charset,因为MSDN说应该加…呵呵
If the code page is set in a page, then Response.Charset should also be set.
另外,文件的编码格式应该与@CODEPAGE一样:
The file format of a Web page must be the same as the @CODEPAGE used in the page.
这就是为什么zblog,pjblog等一些程序要吧文件存成UTF8编码格式的原因.
综上,如果所有的程序都声明了Response.CodePage就不会被Session.CodePage干扰而出现乱码了。所以Session.CodePage还是不能轻易用的!
Spring and Hibernate with BlazeDS
Problem Summary
You want to use Spring and Hibernate with BlazeDS.
Solution Summary
This cookbook entry describes how you can update the store/inventory management example from Christophe Coenraets article Using BlazeDS with Spring with orM data access with Hibernate.
Explanation
Introduction
In his article Using BlazeDS with Spring Christophe Coenraets describes how you can build internet applications with a Flex front-end and a Spring back-end. The article contains a store/inventory management example with database connectivity using the Spring JDBC abstraction framework. This cookbook entry describes how you can update the store/inventory management example with orM data access with Hibernate. Hibernate is one of the most popular persistency frameworks. Since this entry extends the store/inventory management example, it assumes you successfully completed Example 2: Store/inventory management using Flex Remoting.
Step 1: Add the Hibernate libraries
First download Hibernate from http://www.hibernate.org and add the following libraries to /blazeds/tomcat/webapps/blazeds/WEB-INF/lib:
antlr.jar cglib.jar asm.jar asm-attrs.jars commons-collections.jar commons-logging.jar hibernate3.jar jta.jar dom4j.jar log4j.jar
Step 2: Create the mapping file
Since Hibernate needs to know how to load and store objects of the Product class, we need a mapping file to tell Hibernate what table and properties to use. Create a file Product.hbm.xml in /flex-spring/samples/store/java and add the following mapping:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" []> <hibernate-mapping package="flex.samples.spring.store"> <class name="Product" table="PRODUCT"> <id name="productId" type="long" column="PRODUCT_ID" unsaved-value="0"> <generator class="identity"/> </id> <property name="name" column="NAME" length="40"/> <property name="category" column="CATEGORY" length="40"/> <property name="image" column="IMAGE" length="40"/> <property name="price" column="PRICE" type="double"/> <property name="description" column="DESCRIPTION" length="255"/> <property name="qtyInStock" column="QTY_IN_STOCK" type="integer"/> </class> </hibernate-mapping>
Step 3: Create the Hibernate ProductDAO implementation
Now that Hibernate knows how to store our objects, we can implement the ProductDAO interface to use Hibernate persistency. Create a new class HibernateProductDAO in the /flex-spring/samples/store/java directory and add the following lines:
package flex.samples.spring.store;
import java.util.Collection;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
public class HibernateProductDAO implements ProductDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory() {
return this.sessionFactory;
}
public void createProduct(Product product) {
Session session = SessionFactoryUtils.getSession(getSessionFactory(),
false);
try {
session.save(product);
} catch (HibernateException e) {
throw SessionFactoryUtils.convertHibernateAccessException(e);
}
}
public void deleteProduct(Product product) {
Session session = SessionFactoryUtils.getSession(getSessionFactory(),
false);
try {
session.delete(product);
} catch (HibernateException e) {
throw SessionFactoryUtils.convertHibernateAccessException(e);
}
}
public Collection findAll() {
Session session = SessionFactoryUtils.getSession(getSessionFactory(),
false);
try {
return session.createQuery("from Product").list();
} catch (HibernateException e) {
throw SessionFactoryUtils.convertHibernateAccessException(e);
}
}
public void updateProduct(Product product) {
Session session = SessionFactoryUtils.getSession(getSessionFactory(),
false);
try {
session.update(product);
} catch (HibernateException e) {
throw SessionFactoryUtils.convertHibernateAccessException(e);
}
}
}
Step 4: Register the Spring beans
We need to register the new productDAOBean and a Hibernate sessionFactory in the Spring configuration. Transaction supported is added using the HibernateTransactionManager. Register the beans in the applicationContext.xml as follows:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="mappingResources"> <list> <value>flex/samples/spring/store/Product.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> </props> </property> <property name="dataSource"><ref bean="dataSource"/></property> </bean> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory"/> </property> </bean> <bean id="productDAOBeanTarget" class="flex.samples.spring.store.HibernateProductDAO"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="productDAOBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="txManager" /> <property name="target" ref="productDAOBeanTarget" /> <property name="transactionAttributes"> <props> <prop key="create*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
Remove the original productDAOBean configuration.
Step 5: Update the build file
Navigate to /flex-spring/samples/store and open the file build.xml. Update the compile-java target to include the Hibernate library and to copy the mapping file:
<target name="compile-java">
<javac srcdir="java" destdir="${DEPLOY_DIR}/WEB-INF/classes"
classpath="${DEPLOY_DIR}/WEB-INF/lib/spring.jar;${DEPLOY_DIR}/WEB-INF/lib/hibernate3.jar"/>
<copy todir="${DEPLOY_DIR}/WEB-INF/classes/flex/samples/spring/store">
<fileset dir="java" includes="**/*hbm.xml"/>
</copy>
</target>
Step 6: Build the project
* Navigate to /flex-spring/samples/store.
* Execute the following command to compile and deploy the client-side and the server side of the application: ant
Step 7: Run the client application
* Restart Tomcat
* Open a browser, access http://localhost:8400/blazeds/storeadmin/index.html, and test the storeadmin application.
* Open a browser, access http://localhost:8400/blazeds/store/index.html, and test the store application.
[转]javascript 操作cookies 存(设置)、读取、删除函数实例详解
以前一般没想过要在JavaScript里进行COOKIES操作,不过今天碰到了,所以也发一下,作为收藏吧,以下是将这几个功能分别写成了函数.方便使用
<SCRIPT LANGUAGE="JavaScript">
//写cookies函数
function SetCookie(name,value)//两个参数,一个是cookie的名子,一个是值
{
var Days = 30; //此 cookie 将被保存 30 天
var exp = new Date(); //new Date("December 31, 9998");
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
function getCookie(name)//读取cookies函数
{
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) return unescape(arr[2]); return null;
}
function delCookie(name)//删除cookie
{
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval=getCookie(name);
if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}
//简单例子
//SetCookie ("name", www.buslfy.cn)
//alert(getCookie(name));
</script>
<SCRIPT LANGUAGE="JavaScript">
function GetCookieVal(offset)
//获得Cookie解码后的值
{
var endstr = documents.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = documents.cookie.length;
return unescape(documents.cookie.substring(offset, endstr));
}
如果点了确定,只要不清cookie,以后访问都不会再提示,如果不点确定则每次都会提示。放在js文件里,全站包含
<!--
var the_cookie = document.cookie;
var broken_cookie = the_cookie.split(":");
var the_visiteraccepted = unescape(broken_cookie[1]);
//
if (the_visiteraccepted=="undefined"){
var tmp=confirm('中国人何时何地。');
if(tmp==false){
window.close();
}else{
var the_visiteraccepted = 1;
var the_cookie = "ILoveChina=visiteraccepted:" + escape(the_visiteraccepted);
document.cookie = the_cookie;
}
}
//-->
</SCRIPT>
1. Cookie的兼容性问题
Cookie 的格式有2个不同的版本,第一个版本,我们称为Cookie Version 0,是最初由Netscape公司制定的,也被几乎所有的浏览器支持。而较新的版本,Cookie Version 1,则是根据RFC 2109文档制定的。为了确保兼容性,JAVA规定,前面所提到的涉及Cookie的操作都是针对旧版本的Cookie进行的。而新版本的Cookie目前还不被Javax.servlet.http.Cookie包所支持。
2. Cookie的内容
同样的 Cookie的内容的字符限制针对不同的Cookie版本也有不同。在Cookie Version 0中,某些特殊的字符,例如:空格,方括号,圆括号,等于号(=),逗号,双引号,斜杠,问号,@符号,冒号,分号都不能作为Cookie的内容。这也就是为什么我们在例子中设定Cookie的内容为”Test_Content”的原因。
虽然在Cookie Version 1规定中放宽了限制,可以使用这些字符,但是考虑到新版本的Cookie规范目前仍然没有为所有的浏览器所支持,因而为保险起见,我们应该在Cookie的内容中尽量避免使用这些字符
读取cookie的正则表达式
表达式
\w+=[^;]*
示例
ohkoo=Password=mikel&User=mikel; ASPSESSIONIDCCATCBCA=PLALKMLBOAJPBDCDEEHHJJNJ; ASPSESSIONIDQADCTCCC=EPNHNPMBIOFIOCCKHDABBJCL
[转]js操作cookie
初学ajax,昨天做项目的同时,写了一个操作cookies的js框架,比较符合jsp或者asp操作cookies的习惯(因为JavaScript里本身没有这样的对象,操作cookies等于操作字符串,所以比较麻烦)。源代码已经上传点击下载该文件,以下是框架接口说明:
对象:document.xCookie / xCookie (两个对象同等)
方法:
document.xCookie.load(d) 预加载当前已存cookies,参数d为文档对象,默认为当前文档,即document。此函数是预加载,需在所有cookie操作前使用。
document.xCookie.save() 保存对cookies的修改
document.xCookie.clear() 清除当前文档所有cookies
document.xCookie.$(name) 返回以name命名的cookie对象(document.xCookie.cookie类),相当于asp里的 Response.Cookies(name)。用点语法或[]语法访问该cookie的属性值,即 document.xCookie.$(name).prop或document.xCookie.$(name)[prop]。如果属性值不存在,则返回undefined(null)
类:document.xCookie.cookie (操作以name命名的cookie对象,document.xCookie.$(name)返回的就是这个类的实例,所以这个类的实例可以不必单独自行创建)
构造函数:
function(document, name, timeout, path, domain, secure),document为文档对象(必填);name为cookie的名字(必填);timeout为cookie过时设置,单位为分钟,可缺省,默认为暂时保存;后三个参数不在赘述,不明白的请参考有关JavaScript里的cookie知识,可缺省。
方法:
class.read(),读取当前cookie的属性值对(创建类实例时已经执行)
class.write(),写入对当前cookie的修改
class.remove(),删除当前cookie
class.toString(),返回属性值对的字符串表示形式
属性:
class.prop,访问当前cookie的prop属性
举例:
document.xCookie.load();
document.xCookie.$('myname').first='terry';
document.xCookie.$('myname').last='king';
document.xCookie.$('sex').sex='male';
document.xCookie.save();
alert(document.xCookie.$('myname').toString());
alert(document.xCookie.$('sex').toString());
备注,压缩包里一共有两个源文件,xCookie+prototype.js是沿用了prototype(1.4)框架的一些方法,需要prototype框架的支持
另外一个xCookie是没有沿用prototype框架的。
点击下载此文件
Post还是Get
客户端提交调用AjaxUpdater.Update(“GET”,”userValidator.asp”,display);
后,服务器端Request不到userName和Password值
/**
类名:Ajax
创建日期:2008-3-12
版本:1.0
功能说明:
处理异步提交请求,和对请求状态的处理,以及对返回内容类型的分别处理
**/
Ajax={};
//提交请求
//method:post或get方法
//url:服务器端的URL
//callbackMethod:返回响应后的处理函数
Ajax.makeRequest=function (method,url,callbackMethod)
{ //根据浏览器类型创建request对象
if (window.XMLHttpRequest)
{
this.request=new XMLHttpRequest();
}else{
this.request=new ActiveXObject("MSXML2.XMLHTTP");
}
//设置回调函数
this.request.onreadystatechange=callbackMethod;
//设置异步请求
this.request.open(method,url,true);
//发送请求
this.request.send(url);
}
//根据返回状态代码,进行不同的页面异步显示
Ajax.checkReadyState=function(_id)
{
switch(this.request.readyState)
{
case 1:
document.getElementById(_id).innerHTML="Loading....";
break;
case 2:
document.getElementById(_id).innerHTML="Loading....";
break;
case 3:
document.getElementById(_id).innerHTML="Loading....";
break;
case 4://成功返回结果
//alert(this.request.status);
AjaxUpdater.isUpdating=false;
document.getElementById(_id).innerHTML='';
return HTTP.status(this.request.status);
default:
document.getElementById(_id).innerHTML = "An unexpected error has occurred.";
}
}
//返回请求对象的响应属性类型的内容
Ajax.getResponse=function()
{ //如果是返回内容首部含有xml格式的数据,则直接返回xml文档内容
if(this.request.getResponseHeader('Content-Type').indexOf('xml')!=-1)
{
return this.request.responseXML.documentElement;
}else
{//否则返回字符格式的文本内容
//alert(this.request.responseText);
return this.request.responseText;
}
}
/**
类名:AjaxUpdater
创建日期:2008-3-12
版本:1.0
功能说明:
处理异步提交请求,和对请求状态的处理,以及对返回内容类型的分别处理
**/
AjaxUpdater={};
//初始化设置isUpdating属性为false
AjaxUpdater.initialize=function()
{
//isUpdating用于应用程序任何地方确定一个请求是否正在运行
AjaxUpdater.isUpdating=false;
}
//初始化
AjaxUpdater.initialize();
//更新请求对象方法
//method:post或get方法
//service:也就是URL或附加?名=值&名=值的字符串
//callback:是可选参数,因为有一个默认的onResponse方法进行处理
AjaxUpdater.Update=function (method,service,callback)
{
//如果callback为空则默认设置onResponse方法进行处理
if(callback==undefined||callback=="")
{
callback=AjaxUpdater.onResponse;
}
//调用Ajax的发送请求方法进行异步请求
Ajax.makeRequest(method,service,callback);
//设置当前运行标识为true
AjaxUpdater.isUpdating=true;
}
//默认响应方法,当请求成功也就是=200时,将正在运行状态isUpdating设置为false,防止程序状态混乱
//注意:传入的参数loading是默认页面上id为loading的div或其他元素
//因此彼此页面中含有id为loading的元素
AjaxUpdater.onResponse=function ()
{
//返回状态200
if(Ajax.checkReadyState("loading")==200)
{
AjaxUpdater.isUpdating=false;
}
}
function initialize()
{
//alert("userValidator.asp");
AjaxUpdater.Update("GET","userValidator.asp",display);
}
function display()
{
try{
if(Ajax.checkReadyState('loading')=='OK')
{
alert("here");
info=Utilities.getElement("info");
//alert(Ajax.getResponse());
info.innerHTML=Ajax.getResponse();
}
}catch(e)
{
//alert(e);
document.write(e);
}
}
</script>
<body>
<div id="loading"></div>
<div id="info">
<form method="post">
<div>用户登陆</div>
<div>用户名:<input type="text" id="userName" name="userName"/></div>
<div>密码:<input type="text" id="password" name="password"/></div>
<div><input type="button" value="submit" onclick="initialize();" /></div>
</form>
</div>
</body>
</html>
<%
'Response.Write("<div>测试</div>")
'if Request("Action")="login" then
userName=Request.QueryString("userName")
password=Request.QueryString("passWord")
if Request.QueryString("userName")="" or Request.QueryString("password")="" then
Response.Write("<div>Is Empty</div>")
else
Set rs=Server.CreateObject("ADODB.RecordSet")
sql="select * from userInfo where userName='"&userName&"' and password='"&password&"'"
'response.write sql
rs.open sql,conn,2,2
if not rs.EOF then
'Response.Cookies("userInfo")
Response.Write("<div id='panel'><div>我的收藏</div><div>修改资料</div><div>我的好友</div></div>")
else
Response.Write("<div>登陆失败</div>")
end if
end if
'end if
%>
Request的取值方法
一般来说还使用万能的request(“id”)比较好
Request从几个集合取数据是有顺序的,从前到后的顺序依次是 QueryString,Form,最后是ServerVariables。Request对象按照这样的顺序依次搜索这几个集合中的变量,如果有符合的就中止,后面的就不管了。
现在我们来分析下你得问题.
假设有个页面 test.asp?id=111
这里我们的页面是用GET的方法.这时用request.querystring(“id”)与request(“id”)是一样得,应该如果不指定REQUEST得集合,首先就会从Querystring搜索.
而如果我们的页面是用的是POST的方法发送数据给test.asp,那么用request.querystring(“id”)是不行的了(他只能取 GET),而要用request.from(“id”),而如果还用request(“id”)他也能取到数据,但先检测QUERYSTRING的值,显然速度就慢了.
下面是个检测的例子你可以看看:
<%
If Request("submit")<>“” then
Response.Write “直接取:”& Request(“username”) & “
”
Response.Write “取Get:” & Request.QueryString(“username”) & “
”
Response.Write “取Post:” & Request.Form(“username”) & “
”
End if
%>
Flex3 Code key
不多说了:
1377-4260-4983-2510-8542-5740
用STOMP集成Flex3.0和RabbitMQ
用STOMP集成Flex3.0和RabbitMQ
作者 Moxie Zhang译者 宋玮 发布于 2008年3月16日 下午8时48分
社区
Java
主题
RIA,
消息传送
在Flex on Rails上张贴的一篇文章中,Derek Wischusen与我们分享了他使用ActionScript 3 STOMP客户端将RabbitMQ与Flex 3集成在一起的试验。
RabitMQ是一个开源的企业消息传递系统:
RabitMQ是一个完整的、高可靠的企业消息传递系统。RabbitMQ客户端类库及后台程序(broker daemon)可一起被用于创建一个AMQP网络,或者单独使用它们以便给建立起来的网络带来RabbitMQ的好处。
RabitMQ是AMQP协议的实现,该协议是消息传递中间件的一个开放标准。STOMP则是面向流文本的消息传递协议。Wischusen所尝试的是去利用RabbitMQ的STOMP适配器。
为了使读者理解该试验是如何工作的,Wischusen给我们共享了相应的资源和源代码:
o 按照其指南所示步骤,让带有STOMP适配器的RabbitMQ来运行。
o 下载Flex例子应用的项目文件。
接下来,Wischusen解释了这个Flex例子项目到底实现了什么:
该项目有两个单独的应用组成:ImageSender和ImageReceiver。该项目文件也包含了已编译的as3-stomp类库,这样你就无需单独下载它了。
ImageSender和ImageReceiver应用将通过STOMP协议使用RabbitMQ交换消息来进行通讯。为了证明来自两个应用的Flex代码是如何与STOMP客户端一起工作的,Wischusen分享了这一代码片断。
在ImageSender方面:
“stomp” />
…
private function init () : void
{
var ch: ConnectHeaders = new ConnectHeaders();
ch.login = “guest”;
ch.passcode = “guest”
stomp.connect(“localhost”, 61613, ch);
}
…
private function sendImage():void
{
var image: ByteArray = ImageSnapshot.captureImage(canvas).data;
stomp.send(destination, image);
}
在ImageReceiver方面:
“stomp” message=”handleMessages(event)” />
…
private var destination: String = “/queue/images”;
private function init () : void
{
var ch: ConnectHeaders = new ConnectHeaders();
ch.login = “guest”;
ch.passcode = “guest”
stomp.connect(“localhost”, 61613, ch);
stomp.subscribe( destination );
}
…
private function handleMessages(event : MessageEvent) : void
{
var bd: BitmapData = new BitmapData(canvas.width, canvas.height);
var loader : flash.display.Loader = new flash.display.Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBytesLoaded);
loader.loadBytes(event.message.body);
function onBytesLoaded (event : Event) : void
{
var content : DisplayObject = LoaderInfo( event.target ).content;
bd.draw( content );
canvas.graphics.beginBitmapFill(bd);
canvas.graphics.drawRect(0,0, canvas.width, canvas.height);
canvas.graphics.endFill();
}
}
该试验示范了一个图像是如何从Flex应用端(ImageSender)被捕获的,该图像怎么被发送至RabbitMQ服务器,消息如何被发送到消息消费者应用(ImageReceiver),以及这个消息怎样触发了一个事件而从RabbitMQ服务器装载这个图像。这是面向消息的RIA应用概念的一个有趣的演示。
查看英文原文:Integrating Flex 3.0 and RabbitMQ Using STOMP
Flex测试工具RIATest发布Beta版
Flex测试工具RIATest发布Beta版
作者 Moxie Zhang译者 郭晓刚 发布于 2008年3月12日 上午12时40分
社区
Java
主题
RIA
RIATest是一个Flex自动化GUI测试工具,它刚刚公开发布了Beta版。InfoQ为此采访了RIATest的创造者Tigran Najaryan。
Najaryan首先谈到了创造RIATest的目的:
RIATest是一个用来对Adobe Flex 3程序进行自动化GUI测试的工具。创造RIATest的目的是为了给商业和专业开发者提供一个简单、干净的测试自动化方案,帮助他们保证产品的质量。我们在定价上非常激进,一心把测试自动化带给更多的Flex用户,而这些用户以前都负担不起其它的Flex测试自动化方案。
说到RIATest如何工作的时候,Najaryan解释说:
从技术上看,RIATest由两部分组成:Agent和IDE(或者命令行执行器)。Agent呆在浏览器一方,直接与被测程序打交道。Agent提供了组件查看器(Component Inspector),让你检查和监视被测程序的GUI组件及其属性。Agent还通过TCP连接与IDE相连。Agent与IDE在回放期间(IDE向 Agent发送指令并接收结果)以及录制期间(Agent把录下的动作通知给IDE)都经由这个TCP连接相互沟通。
测试脚本是用RIAScript语言写的。RIAScript是一个简化版的ActionScript(另有些微扩展)——因此熟悉ActionScript的开发者很容易学会编写RIATest的测试脚本。
RIATest是用什么开发的?Najaryan回答说:
RIATest从一开始就是作为Flex 3测试自动化工具来设计的,它使用了Flex的测试自动化框架。RIATest IDE是用C++和wxWidgets库写的。RIATest Agent是用Flex 3开发的。
由于现在已经可以见到不少Flex测试工具,所以InfoQ请Najaryan将RIATest与其它工具比如FlexUnit作一下比较:
RIATest作为一个自动化GUI测试工具,与单元测试等其他测试手段是相辅相成的。必须通过多种自动化测试手段才能得到最高质量的保证,自动化GUI测试和单元测试都包括在内。
谈到如何测试连通性,如HTTP请求和SOAP连接:
RIATest内建了按照指定条件自动或手动进行同步的功能,因此即使程序需要与远程数据源通信,RIATest也能完全胜任自动化测试的工作。QA工程师可以通过“'waitfor'”操作让测试脚本与被测程序的组件状态同步。
最后,Najaryan给出了一段测试脚本的例子:
RIATest Script
查看英文原文:RIATest for Flex Released Beta Product
Mikel