Activiti 5.12.1 下载、安装和运行

2013-05-18 Activiti

一、下载和安装

activiti下载:

本例子版本:activiti-5.12.1.zip

http://www.activiti.org/download.html

 

JDK 下载 JDK 6+

本例子版本:jdk7

http://www.oracle.com/technetwork/java/javase/downloads/index.html

eclipse下载 Eclipse Indigo and Juno:

本例子版本:Eclipse Juno (4.2)

http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/juno/SR2/eclipse-jee-juno-SR2-win32.zip

 

解压activiti-5.12.1.zip获取activiti-explorer.war

001

 

activiti-explorer.war 拷贝至Tomcat.(或其他java web服务器,本例为Tomcat 6.0)的webapps目录下

二、运行

启动tomcat,在浏览器打开项目(本例子tomcat端口为8089)

http://localhost:8089/activiti-explorer/

 

003

 

见到这个界面说明项目运行成功了!

默认使用的是内存数据库 H2,下面为数据库表

Table 用户和分组

UserId

Password

Security roles

kermit

kermit

admin

gonzo

gonzo

manager

fozzie

fozzie

user

 

可以使用上面的账号登入系统(本例为kermit)

004

 


Flex4.6 textArea 文字换行 示例

2013-05-13 Flex

###flex4.6 textArea 文字换行 有 几种实现形式,

####法1:在text文字里面直接加 “
”

<s:TextArea  text="这是个 TextArea 分行的例子&amp;#13; http://www.waylau.com "/>

####法2:采用了 TLF 标记 形式

<s:TextArea  width="100%" height="340"   >
		<s:content >
			flex 4.6	<s:span color="#FF0000" fontWeight="bold">这是个 TextArea 分行的例子 </s:span><s:br/>
			<s:span color="#008800"> 采用了 TLF 标记 形式  </s:span> <s:br/>

			<s:a href="http://www.waylau.com" target="_blank">技术支持:www.waylau.com </s:a>.</s:content>
	</s:TextArea>

Flex4.6项目本地右键编译正常,部署后访问不了图片资源。解决

2013-05-11 Tomcat

###问题: 如题 遇到 一个 奇怪的 问题, 项目右键运行 图片显示正常。 但 部署到 web服务器 就 显示不正常了。

PS:图片命名用了中文。 用了英文的貌似显示 都正常。

###解决 初步 认定 可能是 web 服务器 编码所致使

在tomcat/conf/server.xml中找到 Connector 在后面加上 URIEncoding=”UTF-8” 即可

<Connector port="8089" protocol="HTTP/1.1" 
           connectionTimeout="20000" 
           redirectPort="8443"  URIEncoding="UTF-8"/>

惠州(惠州学院)——大亚湾(霞冲镇\金海岸)骑行路线图

2013-05-10 Outdoor

1.惠城区出发时,先骑(新S254)惠南大道 2.到了永湖镇后,左转进入(旧S254)惠澳大道,直走 3.到大亚湾的疏港大道, 4.1 快到石化大道前的一个十字路口(有指往霞冲镇的路标),转左直走就能到达霞冲镇,这是一条新路,左边有一条绿道直达霞冲镇 4.2 或到澳霞立交 左转,进入石化大道,直达霞冲镇 5.过了霞冲镇直走约3公里就是金海岸海滨浴场


SOAP webserivce 和 RESTful webservice 对比及区别

2013-04-25 REST Web

简单对象访问协议(Simple Object Access Protocol,SOAP)是一种基于 XML 的协议,可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME),基于“通用”传输协议是 SOAP的一个优点。它还支持从消息系统到远程过程调用(Remote Procedure Call,RPC)等大量的应用程序。SOAP提供了一系列的标准,如WSRM(WS-Reliable Messaging)形式化契约确保可靠性与安全性,确保异步处理与调用;WS-Security、WS-Transactions和WS-Coordination等标准提供了上下文信息与对话状态管理。

</wbr>

相对而言,SOAP协议属于复杂的、重量级的协议,当前随着Web2.0的兴起,表述性状态转移(Representational State Transfer,REST)逐步成为一个流行的架构风格。REST是一种轻量级的Web Service架构风格,其实现和操作比SOAP和XML-RPC更为简洁,可以完全通过HTTP协议实现,还可以利用缓存Cache来提高响应速度,性能、效率和易用性上都优于SOAP协议。REST架构对资源的操作包括获取、创建、修改和删除资源的操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法,这种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。REST架构尤其适用于完全无状态的CRUD(Create、Read、Update、Delete,创建、读取、更新、删除)操作。

基于REST的软件体系结构风格(Software Architecture Style)称之为面向资源体系架构(Resource-oriented Architecture,ROA)。按照REST原则设计的软件、体系结构,通常被称为“REST式的”(RESTful),在本文中以下称之为RESTful Web服务,以便于和基于SOAP的Web服务区别。 </wbr>

服务器端采用J2EE,客户端采用JSP、Flex、JavaFX、AIR等可以直接调用Servlet,其他的实现技术基本上不能直接调用,但是无论是那种客户端,对于基于SOAP的Web服务或者基于RESTful Web服务务都是支持的,如AJAX的 XMLHttpRequest、Flex的HTTPService等。如下图所示:

客户端和服务器端的通讯方式

 

SOAP
HTTP 的 GET、HEAD 请求本质上应该是安全的调用,即:GET、HEAD 调用不会有任何的副作用,不会造成服务器端状态的改变。对于服务器来说,客户端对某一 URI 做 n 次的 GET、HAED 调用,其状态与没有做调用是一样的,不会发生任何的改变。 HTTP 的 PUT、DELTE 调用,具有幂指相等特性 , 即:客户端对某一 URI 做 n 次的 PUT、DELTE 调用,其效果与做一次的调用是一样的。HTTP 的 GET、HEAD 方法也具有幂指相等特性。 HTTP 这些标准方法在原则上保证你的分布式系统具有这些特性,以帮助构建更加健壮的分布式系统。 安全控制 为了说明问题,基于上面的在线用户管理系统,我们给定以下场景: 参考一开始我们给出的用例图,对于客户端 Client2,我们只希望它能以只读的方式访问 User 和 User List 资源,而 Client1 具有访问所有资源的所有权限。 如何做这样的安全控制? 通行的做法是:所有从客户端 Client2 发出的 HTTP 请求都经过代理服务器 (Proxy Server)。代理服务器制定安全策略:所有经过该代理的访问 User 和 User List 资源的请求只具有读取权限,即:允许 GET/HEAD 操作,而像具有写权限的 PUT/DELTE 是不被允许的。 如果对于 REST,我们看看这样的安全策略是如何部署的。如下图所示: 图 4. REST 与代理服务器 (Proxy Servers) REST 一般代理服务器的实现根据 (URI, HTTP Method) 两元组来决定 HTTP 请求的安全合法性。 当发现类似于(http://localhost:8182/v1/users/{username},DELETE)这样的请求时,予以拒绝。 对于 SOAP,如果我们想借助于既有的代理服务器进行安全控制,会比较尴尬,如下图: 图 5. SOAP 与代理服务器 (Proxy Servers) REST 所有的 SOAP 消息经过代理服务器,只能看到( http://localhost:8182/v1/soap/servlet/messagerouter , HTTP POST)这样的信息,如果代理服务器想知道当前的 HTTP 请求具体做的是什么,必须对 SOAP 的消息体解码,这样的话,意味着要求第三方的代理服务器需要理解当前的 SOAP 消息语义,而这种 SOAP 应用与代理服务器之间的紧耦合关系是不合理的。 关于缓存 众所周知,对于基于网络的分布式应用,网络传输是一个影响应用性能的重要因素。如何使用缓存来节省网络传输带来的开销,这是每一个构建分布式网络应用的开发人员必须考虑的问题。 HTTP 协议带条件的 HTTP GET 请求 (Conditional GET) 被设计用来节省客户端与服务器之间网络传输带来的开销,这也给客户端实现 Cache 机制 ( 包括在客户端与服务器之间的任何代理 ) 提供了可能。HTTP 协议通过 HTTP HEADER 域:If-Modified-Since/Last- Modified,If-None-Match/ETag 实现带条件的 GET 请求。 REST 的应用可以充分地挖掘 HTTP 协议对缓存支持的能力。当客户端第一次发送 HTTP GET 请求给服务器获得内容后,该内容可能被缓存服务器 (Cache Server) 缓存。当下一次客户端请求同样的资源时,缓存可以直接给出响应,而不需要请求远程的服务器获得。而这一切对客户端来说都是透明的。 图 6. REST 与缓存服务器 (Cache Server) REST 而对于 SOAP,情况又是怎样的呢? 使用 HTTP 协议的 SOAP,由于其设计原则上并不像 REST 那样强调与 Web 的工作方式相一致,所以,基于 SOAP 应用很难充分发挥 HTTP 本身的缓存能力,图 7. SOAP 与缓存服务器 (Cache Server) REST 两个因素决定了基于 SOAP 应用的缓存机制要远比 REST 复杂: 其一、所有经过缓存服务器的 SOAP 消息总是 HTTP POST,缓存服务器如果不解码 SOAP 消息体,没法知道该 HTTP 请求是否是想从服务器获得数据。 其二、SOAP 消息所使用的 URI 总是指向 SOAP 的服务器,如本文例子中的 http://localhost:8182/v1/soap/servlet/messagerouter ,这并没有表达真实的资源 URI,其结果是缓存服务器根本不知道那个资源正在被请求,更不用谈进行缓存处理。 关于连接性 在一个纯的 SOAP 应用中,URI 本质上除了用来指示 SOAP 服务器外,本身没有任何意义。与 REST 的不同的是,无法通过 URI 驱动 SOAP 方法调用。例如在我们的例子中,当我们通过 getUserList SOAP 消息获得所有的用户列表后,仍然无法通过既有的信息得到某个具体的用户信息。唯一的方法只有通过 WSDL 的指示,通过调用 getUserByName 获得,getUserList 与 getUserByName 是彼此孤立的。 而对于 REST,情况是完全不同的:通过 http://localhost:8182/v1/users URI 获得用户列表,然后再通过用户列表中所提供的 LINK 属性,例如 <link>http://localhost:8182/v1/users/tester</link> 获得 tester 用户的用户信息。这样的工作方式,非常类似于你在浏览器的某个页面上点击某个 hyperlink, 浏览器帮你自动定向到你想访问的页面,并不依赖任何第三方的信息 REST 构建的系统其系统的扩展能力要强于 SOAP,这可以体现在它的统一接口抽象、代理服务器支持、缓存服务器支持等诸多方面, 而SOAP的成熟性可以给需要提供给多开发语言的,多传输方式的,对于安全性要求较高的接口设计带来便利。   原文载自:http://luckykapok918.blog.163.com/blog/static/20586504320123238260833/

自行车骑行装备的选择

2013-04-24 Outdoor

一、骑行人员装备 从上至下,依次为: 1、骑行头盔:为轻质头盔,以高强度泡沫压制而成,用于头部防护; 2、骑行头巾:多种用途,主要用于排汗遮阳阻隔灰尘; 3、骑行眼镜:按照佩带时间段,镜片可分为多种颜色,一般为深灰色、黄色、白色。深灰色-适合于中午阳光照射充足的时间佩带,以阻隔刺眼的眼光;黄色-适合清晨、黄昏阳光照射相对较暗的时候佩带;白色,适合天气阴暗或晚上佩带。其主要功能在于,阻隔阳光、阻隔风尘; 4、骑行服:骑行人员专用衣服,由多种面料制作而成,可按需选用。其功能主要功能为保暖、速干、透气; 5、骑行袖套:又称为臂套,主要和短袖骑行服搭配穿着,方便拆解,其主要功能为保暖、防晒; 6、骑行手套:为骑行人员专用手套,有半指与全指之分,手掌部位做加厚处理,高档骑行手套均垫有硅胶层,主要用于摔车时,减少伤害,防止擦破手; 7、骑行背包或腰包:骑行背包并没有做特殊规定,主要用于盛装骑行过程所需之物,满足需求即可,并不做特殊要求; 8、骑行裤:为骑行者专用裤子,有长短之分并在臀部配有坐垫,其功能主要为高弹减少腿部于自行车之间的摩擦,同时配备的坐垫减少长时间骑行屁股会疼的状况,提高骑行的舒适性; 9、骑行腿套:如直筒一般,与骑行短裤搭配使用,方便拆解,主要功能为保暖、防晒; 10、骑行袜:为骑行者专用袜子,按照COOLMAX含量可分为多种,骑行者可按照骑行时间的长短和骑行活动的强度来选用适合穿着的骑行袜; 11、绑腿:又名束带主要用于扎结裤腿角,防止裤腿绞进链条,以保障骑行的安全; 12、骑行鞋:为骑行者专用鞋子,同样可分为多种,有山地骑行鞋与公路骑行鞋之分,可按照所骑自行车款式进行选择,如自行车配备专用脚蹬,则骑行鞋必须选用锁鞋; 13、骑行鞋套:骑行鞋套用于骑行锁鞋的搭配,有减少风阻,防污保暖等用途。

 

二、车载装备 从自行车前头往后依次有: 1、打气桶:一般为便携装,安置于前叉部位; 2、车首包:又名车把包、车前包常见于山地车装备中。适合长途骑行装载物品之用; 3、车灯\尾灯:常见于夜间骑行的自行车中,照明警示用; 4、喇叭:有气喇叭与电喇叭之分,可按需取用,功能并无太大差别,只是发声装置不同; 5、三角包:隶属于包裹类,作用同于车首包,只是安装部位不同,另还有尾包-安装于自行车座立管部位,驮包安装于自行车后坐部位;车架包,位于车头与车管部位 6、水壶:有多种可选,无需专门配备,主要用于盛装在骑行过程中所需要饮用的水。

  1. 水壶架:放置水壶
  2. 码表:显示里程,测速
  3. 扶把(副把):减少手部疲劳 10.货架(后车架):用于长途骑行装载驮包用 11.挡泥板:雨天必备 12.硅胶坐垫:保护小DD,长途适用 13.护链贴:防止链条脱落与车架激烈摩擦 14.车锁:不多说 15.修补工具:翘胎棒、摩擦片、胶水、补胎片、内六角、一字十字螺丝刀、扳手。。太多了,见下图

 

 


DOM4J介绍与代码示例

2013-04-18 Java

原文摘自:http://zhangjunhd.blog.51cto.com/113473/126310

DOM4J是dom4j.org出品的一个开源XML解析包。Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。

DOM4J下载jar包:http://downloads.sourceforge.net/dom4j/dom4j-1.6.1.jar
JAXEN(对XPath的支持):http://dist.codehaus.org/jaxen/distributions/jaxen-1.1.1.zip
1.DOM4J主要接口
DOM4J主要接口都在org.dom4j这个包里定义。
-Node为所有的dom4j中XML节点定义了多态行为;
-Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为;
|-Element 定义XML 元素;
|-Document定义了XML文档;
-DocumentType 定义XML DOCTYPE声明;
-Entity定义 XML entity;
-Attribute定义了XML的属性;
-ProcessingInstruction 定义 XML 处理指令;
-CharacterData是一个标识借口,标识基于字符的节点。如CDATA,Comment, Text;
|- CDATA 定义了XML CDATA 区域;
|-Text 定义XML 文本节点;
|- Comment 定义了XML注释的行为;
2.创建XML文档
示例xml:students.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="students.xsl"?>
<students>
<!--A Student Catalog-->
<student sn="01">
<name>sam</name>
<age>18</age>
</student>
<student sn="02">
<name>lin</name>
<age>20</age>
</student>
</students>
下面是用dom4j创建上述文档,通过两种方式创建,一种是调用dom4j提供的方法,一种是通过字符串转换。
XmlGen.java
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;
public class XmlGen {
public Document generateDocumentByMethod() {
Document document = DocumentHelper.createDocument();
// ProcessingInstruction
Map<String, String> inMap = new HashMap<String, String>();
inMap.put("type", "text/xsl");
inMap.put("href", "students.xsl");
document.addProcessingInstruction("xml-stylesheet", inMap);
// root element
Element studentsElement = document.addElement("students");
studentsElement.addComment("An Student Catalog");
// son element
Element stuElement = studentsElement.addElement("student");
stuElement.addAttribute("sn", "01");
Element nameElement = stuElement.addElement("name");
nameElement.setText("sam");
Element ageElement = stuElement.addElement("age");
ageElement.setText("18");
// son element
Element anotherStuElement = studentsElement.addElement("student");
anotherStuElement.addAttribute("sn", "02");
Element anotherNameElement = anotherStuElement.addElement("name");
anotherNameElement.setText("lin");
Element anotherAgeElement = anotherStuElement.addElement("age");
anotherAgeElement.setText("20");
return document;
}
public Document generateDocumentByString() {
String text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<?xml-stylesheet type=\"text/xsl\" href=\"students.xsl\"?>" +
"<students><!--An Student Catalog--> <student sn=\"01\">" +
"<name>sam</name><age>18</age></student><student sn=\"02\">" +
"<name>lin</name><age>20</age></student></students>";
Document document = null;
try {
document = DocumentHelper.parseText(text);
} catch (DocumentException e) {
e.printStackTrace();
}
return document;
}
public void saveDocument(Document document, File outputXml) {
try {
// 美化格式
OutputFormat format = OutputFormat.createPrettyPrint();
/*// 缩减格式
OutputFormat format = OutputFormat.createCompactFormat();*/
/*// 指定XML编码
format.setEncoding("GBK");*/
XMLWriter output = new XMLWriter(new FileWriter(outputXml), format);
output.write(document);
output.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] argv) {
XmlGen dom4j = new XmlGen();
Document document = null;
// document=dom4j.generateDocumentByMethod();
document = dom4j.generateDocumentByString();
dom4j.saveDocument(document, new File("output.xml"));
}
}
方法generateDocumentByMethod()通过调用方法构建xml文档:
1.使用DocumentHelper得到Document实例
Document document = DocumentHelper.createDocument();
2.创建Processing Instruction
document.addProcessingInstruction("xml-stylesheet", inMap);
3.创建元素Element
Element studentsElement = document.addElement("students");
4.为元素添加注释Comment
studentsElement.addComment("An Student Catalog");
5.为元素添加属性
studentsElement.addComment("An Student Catalog");
6.为元素添加文本值Text
ageElement.setText("18");
方法generateDocumentByString()通过字符串转换直接构建xml文档,使用DocumentHelper.parseText()来实现.
document = DocumentHelper.parseText(text);
方法saveDocument(Document document, File outputXml)将文档输出到文件保存,可指定字符编码,可指定格式化输出。
3.修改XML文档
这里使用xpath来定位待修改的元素和属性,需要jaxen的支持。
示例中将students-gen.xml的第一个student元素的sn属性改为001,其子元素name内容改为jeff。
XmlMod.java
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class XmlMod {
public void modifyDocument(File inputXml) {
try {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(inputXml);
List list = document.selectNodes("//students/student/@sn");
Iterator iter = list.iterator();
while (iter.hasNext()) {
Attribute attribute = (Attribute) iter.next();
if (attribute.getValue().equals("01"))
attribute.setValue("001");
}
list = document.selectNodes("//students/student");
iter = list.iterator();
while (iter.hasNext()) {
Element element = (Element) iter.next();
Iterator iterator = element.elementIterator("name");
while (iterator.hasNext()) {
Element nameElement = (Element) iterator.next();
if (nameElement.getText().equals("sam"))
nameElement.setText("jeff");
}
}
XMLWriter output = new XMLWriter(new FileWriter(new File(
"students-modified.xml")));
output.write(document);
output.close();
}
catch (DocumentException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] argv) {
XmlMod dom4jParser = new XmlMod();
dom4jParser.modifyDocument(new File("students-gen.xml"));
}
}
1.使用File定位文件资源,并基于此获得Document实例
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(inputXml);
2.Document实例的selectNodes方法可以传入xpath,并返回一个List实例,基于此使用迭代器,完成特定的应用
List list = document.selectNodes("//students/student/@sn");
4.遍历XML文档
这里提供两种遍历方法,一种是基于迭代的遍历,一种是基于Visitor模式的遍历。
XmlTra.java
import java.io.File;
import java.util.Iterator;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.ProcessingInstruction;
import org.dom4j.VisitorSupport;
import org.dom4j.io.SAXReader;
public class XmlTra {
private File inputXml;
public XmlTra(File inputXml) {
this.inputXml = inputXml;
}
public Document getDocument() {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(inputXml);
} catch (DocumentException e) {
e.printStackTrace();
}
return document;
}
public Element getRootElement() {
return getDocument().getRootElement();
}
public void traversalDocumentByIterator() {
Element root = getRootElement();
// 枚举根节点下所有子节点
for (Iterator ie = root.elementIterator(); ie.hasNext();) {
System.out.println("======");
Element element = (Element) ie.next();
System.out.println(element.getName());
// 枚举属性
for (Iterator ia = element.attributeIterator(); ia.hasNext();) {
Attribute attribute = (Attribute) ia.next();
System.out.println(attribute.getName() + ":"
+ attribute.getData());
}
// 枚举当前节点下所有子节点
for (Iterator ieson = element.elementIterator(); ieson.hasNext();) {
Element elementSon = (Element) ieson.next();
System.out.println(elementSon.getName() + ":"
+ elementSon.getText());
}
}
}
public void traversalDocumentByVisitor() {
getDocument().accept(new MyVisitor());
}
/**
* 定义自己的访问者类
*/
private static class MyVisitor extends VisitorSupport {
/**
* 对于属性节点,打印属性的名字和值
*/
public void visit(Attribute node) {
System.out.println("attribute : " + node.getName() + " = "
+ node.getValue());
}
/**
* 对于处理指令节点,打印处理指令目标和数据
*/
public void visit(ProcessingInstruction node) {
System.out.println("PI : " + node.getTarget() + " "
+ node.getText());
}
/**
* 对于元素节点,判断是否只包含文本内容,如是,则打印标记的名字和 元素的内容。如果不是,则只打印标记的名字
*/
public void visit(Element node) {
if (node.isTextOnly())
System.out.println("element : " + node.getName() + " = "
+ node.getText());
else
System.out.println("--------" + node.getName() + "--------");
}
}
public static void main(String[] argv) {
XmlTra dom4jParser = new XmlTra(new File("students-gen.xml"));
// dom4jParser.traversalDocumentByIterator();
dom4jParser.traversalDocumentByVisitor();
}
}
方法traversalDocumentByIterator()提供一种基于迭代的遍历实现,每个Element通过elementIterator()和attributeIterator()取代其子元素和属性的迭代器。
Visitor是GOF设计模式之一。其主要原理就是两种类互相保有对方的引用,并且一种作为Visitor去访问许多Visitable。DOM4J中的Visitor模式只需要自定一个类实现Visitor接口即可。
public class MyVisitor extends VisitorSupport {
public void visit(Element element) {
System.out.println(element.getName());
}
public void visit(Attribute attr) {
System.out.println(attr.getName());
}
}
调用: root.accept(new MyVisitor())
Visitor接口提供多种Visit()的重载,根据XML不同的对象,将采用不同的方式来访问。上面是给出的Element和Attribute的简单实现,一般比较常用的就是这两个。VisitorSupport是DOM4J提供的默认适配器,Visitor接口的Default Adapter模式,这个模式给出了各种visit(*)的空实现,以便简化代码。
注意,这个Visitor是自动遍历所有子节点的。如果是root.accept(MyVisitor),将遍历子节点。我第一次用的时候,认为是需要自己遍历,便在递归中调用Visitor,结果可想而知。
5.使用ElementHandler
XmlHandler.java
import java.io.File;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.ElementHandler;
import org.dom4j.ElementPath;
import org.dom4j.io.SAXReader;
public class XmlHandler {
public static void main(String[] args) {
SAXReader saxReader = new SAXReader();
File file = new File("students.xml");
try {
// 添加一个ElementHandler实例。
saxReader.addHandler("/students/student", newStudentHandler());
saxReader.read(file);
} catch (DocumentException e) {
System.out.println(e.getMessage());
}
}
/**
* 定义StudentHandler处理器类,对<student>元素进行处理。
*/
private static class StudentHandler implements ElementHandler {
public void .Start(ElementPath path) {
Element elt = path.getCurrent();
System.out.println("Found student: " + elt.attribut.ue("sn"));
// 添加对子元素<name>的处理器。
path.addHandler("name", new NameHandler());
}
public void .End(ElementPath path) {
// 移除对子元素<name>的处理器。
path.removeHandler("name");
}
}
/**
* 定义NameHandler处理器类,对<student>的<name>子元素进行处理。
*/
private static class NameHandler implements ElementHandler {
public void .Start(ElementPath path) {
System.out.println("path : " + path.getPath());
}
public void .End(ElementPath path) {
Element elt = path.getCurrent();
// 输出<name>元素的名字和它的文本内容。
System.out.println(elt.getName() + " : " + elt.getText());
}
}
}
6.使用XSLT转换XML
这里必须使用JAXP的支持。
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import org.dom4j.Document;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
……
public Document styleDocument(Document document, String stylesheet)
throws Exception {
// load the transformer using JAXP
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(newStreamSource(stylesheet));
// now lets style the given document
DocumentSource source = new DocumentSource(document);
DocumentResult result = new DocumentResult();
transformer.transform(source, result);
// return the transformed document
Document transformedDoc = result.getDocument();
return transformedDoc;
}
……
 

SecurityError Error 2148 SWF 不能访问本地资源

2013-04-13 Flash

##错误提示:

SWF 文件不能被本地访问 不能访问本地 只有仅限于文件系统的 SWF 文件和可信的本地 SWF 文件可以访问本地资源

##错误信息:

SecurityError: Error #2148: SWF 文件 D:\demo\demo.swf 不能访问本地资源 D:\demo\demo\bin-debug\textLayout_4.0.0.10485.swf。只有仅限于文件系统的 SWF 文件和可信的本地 SWF 文件可以访问本地资源。

##解决方法:

###第一种办法

在Flash插件上右键->全局设置->高级->开发人员工具->受信任的位置设置->添加 ,然后添加你的文件或者文件夹即可。

说明:在本地测试期间,Flash Player 可以显示阻止应用程序正常运行的安全警告。您可以使用“受信任位置设置”面板将您自己的 SWF 或 FLV 内容指定为可信内容,从而解决这一问题。您可以将个别文件的路径指定为可信路径,或者指定文件夹为可信文件夹。可信文件夹中的所有文件及其任何子文件夹也会受信任。使用此选项卡可指定您计算机上包含您信任的 SWF 或 FLV 内容的位置。可信内容不遵循阻止内容访问 Internet 和本地计算机文件系统的安全规则。

###第二种方法:

在C:\WINDOWS\system32\Macromed\Flash\FlashPlayerTrust目录下添加一个文件,比如:1.txt(文件名可任意起),文件内容为项目的路径,当然也可以设置为“D:\” 说明: 为了让你的Flash在用户硬盘中拥有同时访问网络和本地的能力,你必须在用户计算机的FlashPlayerTrust目录中为你的Flash添加权限. FlashPlayerTrust 配置文件。 这些是列出受信任路径的简单文本文件。这些文件由可执行的安装程序创建。当安装程序将 SWF 安装到用户的计算机时, 它能够安装信任的配置文件并指定 SWF 是受信任的。


Flex4.6 用Lable自定义LinkButton

2013-04-08 Flex

很简单,先是继承Lable ,而后 设置相关属性,比如 小手鼠标、下划线等

package com.waylau.eagleos.components
{
	import spark.components.Label;

	public class LinkButton extends Label
	{
		public function LinkButton()
		{
			super();

			this.useHandCursor = true ;
			this.buttonMode = true ;
			this.mouseChildren = false ;

			this.setStyle("textDecoration","underline");
		}
	}
}

Golang strings.Split获取字符串中的url/域名的简易方法

2013-04-07 Golang

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println("Hello World!")

	a := "golang strings.Split获取字符串中的url/域名的简易方法http://www.waylau.com/golang-strings-split-get-url/"
	a1 := strings.Split(a, "//")[1]
	a2 := strings.Split(a1, "/")[0]

	fmt.Println(a1) //输出为:www.waylau.com/golang-strings-split-get-url/
	fmt.Println(a2) //输出为:www.waylau.com
}

惠州——平海古城、海滨温泉、巽寮湾-旅游攻略

2013-04-06 Outdoor

1.在惠州汽车站。乘坐惠州——惠东汽车到达惠东汽车站(18元),转乘惠东——港口专线巴士(18元),至平海镇下车,下车向巷子里走约200米 ,见 城墙,即是古城

其实,平海镇方圆不大,东南西北四个门都见完了也就 几十分钟的事情。城内有几个庙。 恰逢清明节,百姓插旗烧香祭祖,院门大开,也算是领略了风俗民情。 城内无吃饭的地方,吃饭在下车的大路边。 在沙县吃了一碗鸡腿饭13元。

2.平海古城转车去海滨温泉就有所不便,没有的士,也没有班车,上了摩托35元,也只能认了,自己走的话大概要十几公里。 一路狂飙,披头散发,直接送到海滨温泉旅游区门口。

海滨温泉门票是团购的100+,因为是过节临时加多了10元,不限时,貌似营业到晚上12点 去到那里 大概是下午1点半左右,里面大大小小温泉40多个,各种药池,花池,酒池 ,不过里面的温水是不是地热的水就不好说了~ 提供免费的花生小吃还有饮料,橙汁兑水的吧,淡出鸟来 还有花生都不脆,感觉过气的。 另外有小番薯提供,这个不错。 吃了串鱼丸,三颗10元。

泡了一圈,发觉才2点多,休息了一下又去平泡了一圈。其实不能泡太久。 熬到四点过,有歌舞看,走了,不看了。 出门,发现搭车又不便了。决定走到巽寮镇。距离也就是十几公里。(其实是有去惠东的巴士可以搭的) 走了一半路程,天已经暗了。有哥们停车顺了一段路,都是来泡泉的,有亲切感。还是有车好,一脚油门,几分钟就到了酒店。 我是团购的海景山庄,100+标双,到店需要观海的房间的又要对加钱。 酒店内的设施一般,晚上定点放热水。 位置不错,基本上躺床上就能见到海 附近没有吃货,全是酒店。走约两三公里就到镇上。淡季,海鲜还是这么贵~

3.第二天起来,约了隔壁的几个家伙一起去巽寮湾出海打鱼。 一出门就下雨了,我汗。 酒店附近不能直接下海,要走一两公里到滨海度假村有入口可以进海滩。 也没捡贝壳,光避雨去了。附近都是待建的工地。一片荒凉。 天晴上了渔船打鱼,80元包船,打到都是自己的。 结果一趟来回就是几个濑尿虾,不够吃啊。又买了条鱼,叫渔家帮忙煮了。 坐渔家的快艇还是有快感,擦,一条鱼带加工费要了120元

4.附近还有天后宫岭南民俗文化商业街, 酒吧一条街还在招商,人影木有。 商业街有妈祖庙。 天又下雨,走出街到大路,坐车回惠东17元 总结: 路费 100+ 打鱼 80 吃饭 200+ 交通不是很方便。 2013-4-5


Golang 实现的一个小游戏--猜数字

2013-04-06 Golang Game

随机生成一个数字,输入一个数字看是否匹对,匹配则结速,反之提示是大了还是小了,

代码如下: package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"time"
)
var (
	endNum int //设置生成数的范围
)
func main() {
	i := createRandomNumber(endNum)
	//fmt.Println("生成规定范围内的整数:", i)    //本句调试用

	fmt.Println("请输入整数,范围为:0-", endNum)

	flag := true
	reader := bufio.NewReader(os.Stdin)

	for flag {
		data, _, _ := reader.ReadLine()

		command, err := strconv.Atoi(string(data)) //string to int,并作输入格式判断
		if err != nil {
			fmt.Println("格式不对,请输入数字")
		} else {

			fmt.Println("你输入的数字:", command)

			if command == i {
				flag = false
				fmt.Println("恭喜你,答对了~")
			} else if command &lt; i {
				fmt.Println("你输入的数字小于生成的数字,别灰心!再来一次~")
			} else if command &gt; i {
				fmt.Println("你输入的数字大于生成的数字,别灰心!再来一次~")
			}
		}
	}
}
func init() {
	endNum = 10
}

//生成规定范围内的整数
//设置起始数字范围,0开始,endNum截止
func createRandomNumber(endNum int) int {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return r.Intn(endNum)
}

golang实现字符串逆序,不允许临时变量的原地逆序

2013-04-06 Golang

package main

import (
	"fmt"
)

var (
	s1    string
)
func main() {
	fmt.Println(s1)
	fmt.Println(converString(s1))
}
func init() {
	s1 = "我爱你waylau.com"
}
func reverseString(s string) string {
	str := []rune(s)

	for i, j := 0, len(str)-1; i &lt; j; i, j = i+1, j-1 {
		str[i], str[j] = str[j], str[i]
	}

	return string(str)
}

后台输入为

我爱你waylau.com
moc.ualyaw你爱我


Flex的一些总结

2013-03-26 Flex

##Loader与URLLoader,SWFLoader

(1) Loader Loader 类可用于加载 SWF 文件或图像(JPG、PNG 或 GIF)文件。 使用 load() 方法来启动加载。 被加载的显示对象将作为 Loader 对象的子级添加。 (2)URLLoader URLLoader 类以文本、二进制数据或 URL 编码变量的形式从 URL 下载数据。 在下载文本文件、XML 或其它用于动态数据驱动应用程序的信息时,它很有用。URLLoader 对象会先从 URL 中下载所有数据,然后才将数据用于 ActionScript。 它会发出有关下载进度的通知,通过 bytesLoaded 和bytesTotal 属性以及已调度的事件,可以监视下载进度。在加载非常大的视频文件(如 FLV 的视频文件)时,可能会出现内存不足错误。

区别:一个用来加载可显示数据,一个用来加载非显示数据因为loader是继承与容器类的,所以首先它是个容器,而URLLoader 是继承与EventDispatcher,它不是容器URLLoader 类以文本、二进制数据或 URL 编码变量的形式从 URL 下载数据,在加载非常大的视频文件(如 FLV 的视频文件)时,可能会出现内存不足错误,返回的数据在data属性里面而loader多加载图片,swf等可视化对象,加载后作为唯一的子对象显示在列表上。

应用范围 Loader: 多用于swf,图片(jpg,png,gif) URLLoader: 多用于文本文件(xml,php,jsp…) 使用方法

    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); 
    private function loadComplete(event:Event)
    { 
        trace("done");
        addChild(loader);
    }

    //URLLoader:
    xmlLoader.dataFormat=URLLoaderDataFormat.TEXT; 
    xmlLoader.addEventListener(Event.COMPLETE,xmlLoaded); 
    private function xmlLoaded(event:Event) { 
        try {
            myXML = XML(event.target.data);area.text=myXML;
        }catch (e:TypeError) 
        {
            area.text="Load faild:\n"+e.message;
        } 
    }  Loader 在使用Loader来加载数据时,添加侦听事件时,注意一定要给Loader的 contentLoaderInfo属性增加事件,而不是给Loader对象增加事件。
 var loader:Loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITYERROR, securityErrorHandler); loader.contentLoaderInfo.addEventListener(IOErrorEvent.IOERROR, ioErrorHandler);

(3)可以使用SWFLoader和Loader两个类来加载子应用程序,多数情况下我们使用SWFLoader。它是Loader的一个包装类,提供了很多附加功能,使加载子应用程序更简单。 SWFLoader有如下特征: 支持flex的样式和特效;而Loader类却不支持任何固有的样式和特效。 方便管理加载进度;如果使用Loader则首先要获取LoaderInfo引用。

是一个UIComponent组件。SWFLoader它自己管理了所有子显示对象,不需要添加多余的代码。 自动缩放显示内容的大小

可以加载Application以外的实现类,如果检测到不是一个Application,会自动进行处理。 可以处理不同的版本。Loader不支持加载不同的编译版本

当使用Loader加载不是受信任区域的swf时,必须提供一个遮罩来重新定位,否则它会显示在屏幕外面: 代码 import flash.display.*; import flash.net.URLRequest; var rect:Shape = new Shape(); rect.graphics.beginFill(0xFFFFFF); rect.graphics.drawRect(0, 0, 100, 100); addChild(rect); var ldr:Loader = new Loader(); ldr.mask = rect; var url:String = “http://www.unknown.example.com/content.swf”; var urlReq:URLRequest = new URLRequest(url); ldr.load(urlReq); addChild(ldr);

SWFLoader加载外部swf是一个很好的方法,在进行Flex游戏开发的时候,我们通常会需要很多Flash提供的游戏角色,这些角色可以每个都是一个单独的swf,也可以是存在于一个swf文件中的各个元件。两种方法各有优劣: 1. 单独的swf,每个角色独立性很强,可以在需要的时候才加载。未来修改角色也不会影响到其它角色。但是会有很多的swf需要管理。 2. 每个角色是一个元件,存在于一个swf中,这种方法比较容易管理资源,比较干净。但是修改一个角色都需要重新编译swf,可能会误操作影响其它的元件。而且一次加载所有角色,可能会加载许多不必要的元件,浪费带宽。

两种方法怎么选择,根据项目读者根据以下几个问题考虑: 1. 你的所有元件相互之间是否又很多公用元件?如果是的话,可以考虑放到一个swf中,因为这样会降低所有元件的文件量。 2. 你的所有元件是否都继承同一些类,实现同一些接口,调用同一些类?如果是的话,可以考虑放到一个swf中,这样比较容易管理类包,而且降低swf的文件量,因为共有的类只编译一次。 3. 你的所有元件是否完全独立,没有任何关系?如果是的话,你可以考虑每个角色独立的swf。 具体实现代码如下:

<?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"
               creationComplete="init()"
               >
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            import mx.controls.SWFLoader;
            import mx.core.UIComponent;

            private var swfLoader:SWFLoader = new SWFLoader();
            private function init():void{
                swfLoader.addEventListener(Event.COMPLETE,swfLoadComplete);
                swfLoader.load("assets/fishmomo.swf");
            }
            private function swfLoadComplete(e:Event):void{
                /**
                 * 将整个swf都加载到flex舞台上
                 * 此方法将每个flex要用的资源做成单独的swf,需要时才加载进来
                 */ 
                addElement(swfLoader);
                var swf:MovieClip = swfLoader.content as MovieClip;
                //fish 是 swf主舞台上的一个鱼对象,属性命名为fish
                //调用舞台上fish元件的say方法
                swf.fish.say("Load a swf");

                /**
                 * 此方法可以把所有的flex要用的资源放到一个swf中
                 * 把需要在flex中使用的元件链接到一个类,并将此元件拖到flash舞台
                 * 通过类名,随意显示其中一个元件到flex舞台
                 */ 
                var FishSymbol:Object = swfLoader.content.loaderInfo.applicationDomain.getDefinition("Fish");
                var f:MovieClip = new FishSymbol() as MovieClip;
                //调用元件的say方法
                f.say("Load a symbol within a swf");
                var ui:UIComponent = new UIComponent();
                ui.addChild(f);
                addElement(ui);
            }
        ]]>
    </fx:Script>
</s:Application>

##导致内存泄露的一些情况:

事件监听: 对父级对象加了监听函数,会造成内存泄露,例:

override protected function mouseDownHandler(…):void { 
systemManager.addEventListener(“mouseUp”, mouseUpHandler); …… 
}  解决: 在销毁对象的时候,remove掉这些监听,虽然弱引用也可以避免这些问题,但自己掌控感觉更好。 但以下几种情况不会造成内存泄露: 弱引用:

someObject.addEventListener(MouseClick.CLICK, handlerFunction, false, 0, true);  对自己的引用:

this.addEventListener(MouseClick.CLICK, handlerFunction);  子对象的引用: 

private var childObject:UIComponent = new UIComponent; addChild(childObject); childObject.addEventListener(MouseEvent.CLICK, clickHandler);  总之…有addEventListener,就removeEventListener一下吧,要为自己做的事负责~哈哈

清除引用 remove掉子对象后并不会删除该对象,他还保留在内存中,应该将引用设置为null removeChildren(obj); obj = null;

静态成员 Class (或MXML)中有: public static var _eventService : MyService=new MyService(); 解决:在dispose时,需要设置: _eventService =null;

module (未解决) moduleLoader unloadModule后 ModuleInfo 并不会被GC. Garbage Collection in a MultiCore Modular Pipes Application 这篇文章介绍了一种GC策略,感觉对于ModuleInfo 的GC无效。 (未尝试、未遇到)

CSS样式 module 中如果使用了shell的CSS定义或是 这样的定义,那么这个module将不能GC. 弹出的窗口应该是同样的结果. 解决方法,使用动态CSS文件 module init中 StyleManager.loadStyleDeclarations(“css/myStyle.swf”); module dispose中 StyleManager.unloadStyleDeclarations(“css/myStyle.swf”);

TextInput/Textarea(未解决) 如果module中有window使用了TextInput/Textarea控件,不点击没有问题,只要点上去,那么很遗憾了,module和所在窗体将不能被GC. 这个BUG非常严重,目前还没有解决方法。 memory leak when using TextInput and TextArea when click the keyboard 这里面附加的解决方法无效。 通过profiler分析,应该和Focusmanager有关,只有一点击就不会释放。

CursorManager.setCursor 使用了 cursorID = CursorManager.setCursor(iconClosed); dispose时要 CursorManager.removeCursor(cursorID);

Bitmap 如果使用Bitmap,结束时需要调用其dispose方法,否则内存消耗巨大。 另外,BitmapData是可以共享使用的,多个Bitmap可以使用同一BitmapData,节省不少内存。 var bmp:Bitmap =new Bitmap(); …….. if (bmp.bitmapData!=null) { bmp.bitmapData.dispose(); } Image 包含了Image对象时,在removeChildren时会造成不能释放(测试多次,结果不一,建议还是做如下处理)。 解决: img.source = null; this.removeChild(img); img = null;

Loader、SWFLoader、声音、视频、Effect等… 如果是加载SWF文件,先停止播放。 停止声音的播放 停止正在播放的影片剪辑(Movieclip) 关闭任何连接的网络对象,例如Loader正在加载,要先close。 取消对摄像头或者麦克风的引用 取消事件监听器 停止任何正在运行的定时器,clearInterval() 停止任何Timer对象,timer.stop() 停止正在播放的效果(Effect) 其他

binding也疑似有memory leak 问题。 引用以及内存泄露相关博文和资料: http://blogs.adobe.com/aharui/2007/03/garbagecollectionandmemory.html http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/ http://www.cnblogs.com/janyou/archive/2008/11/25/1340753.html http://www.dreamingwell.com/articles/archives/2008/05/understandingm.php 总结:由于之前Flash一直是在网页上使用,一般网页都是看完就关掉的,估计Adobe在内存回收这块也没有下太大的功夫, 现在AIR的出现使得内存管理也相当重要了,并且,AIR本身对内存的消耗就相当大,一个没有任何内容的初始创建的AIR程序,就得占掉10-20M+的内存…AIR还需改善.

##Modules

为什么要模块化;模块化提供了分离应用程序代码到不同的swf文件上以便减少下载时间和文件大小。 使用Modules的好处是:

  1. 主应用程序开始时不需马上下载modules。应用程序会根据需求载入和卸载modules。

  2. 由于每个modules独立于其他应用程序modules,当需要改变一个modules时,你只需要重编译这个modules而不是整个应用程序。模块化可创建模块化应用程序是提高Flex框架性能的重要方面,提供更多能力控制下载时间和文件大小,使用modules,你可以根据哪些可被独立载入,哪些可被其他程序使用而分离应用程序代码。

优点是合理分割了主Application,模块化开发。更小的SWF文件体积,配合RSL和延迟加载策略,大大减少用户等待时间。

缺点就是容易引起内存泄露。

##RSL

RSL(Runtime Shared Library),即运行时加载库。当前L主要有3个级别的RSL,一个是Standard RSL(即一个网站内共享),一个是Cross-domain RSL(跨域共享),最后一个也是最关键的是Framework RSL(Flex框架共享)。 功能说明 Flex Builder在默认情况下,编译的每个程序都是独立的。每个程序都包含了所需类的一个副本,例如:在多个程序中都用到了VBox这个控件,那么每个程序都要独立的拥有一个VBox类。由此造成了程序代码的重复,使得代码量增大很多。而RSL正是解决此问题的一种方法,它可以把共享代码提取出来,然后在相同域的程序之间进行共享。这些共享代码不会再编译进程序,而是放在单独的库中,供运行时加载。另外,RSL也可以在客户端进行缓存,因此不需要在每次使用程序时重复下载。

RSL(Runtime shared libraries)即动态链接库,在程序运行时由FlashPlayer动态加载。静态链接库是SWC文件,通过编译器的library-path和include-libraries 编译进应用程序。采用静态链接的应用程序SWF会产生比较大的文件以及更长的下载时间。使用RSL的应用程序载入时间短且文件比较小,而且提高了内存使用效率,只是 在开始需要花点时间下载RSL。RSL的强大体现在多个应用程序共享公共代码时,因为RSL只需要被下载一次,多个应用程序动态链接到相同的RSL,访问其中已经缓存在客 户端的资源。 使用RSL: (1).在项目文件夹中点右建,选择”properties”-“Flex Build Path”-“Library Path” (2).该选项卡上我们看到”FrameWork linkage”,默认是”Merged into cdoe”(FLEX4默认是RSL) (3).点开下拉,选择”runtime shared library(RSL)” (4).针对自定义的SWC,修改其link type为RSL,选择None,同时勾上Automatically extract swf to deployment path(自动将SWF提取到部署路径)。如果想对不同域的RSL共享,则选择Digests(摘要),同时指定其Policy file url(策略文件)。具体可参考FLEX SDK中的SWC文件处理方式。 (5).点击OK

##SWC

SWC 文件是类似 zip 的文件。静态链接库是SWC文件,通过编译器的library-path和include-libraries编译进应用程序。新建Flex Library Object或使用compc命令可以制作SWC。

##E4X E4X是在ECMA-357标准中定义的,并成为AS3的一部分。优点是提供更简明和可读性强的语法从XML中查找和提取数据。

##profile工具 可以很方便地观察对象的创建和销毁,帮助检查内存泄露问题。

##FlexUnit FlexUnit - Flex单元测试框架

##其他 1、flex生成出来的文件都是很大,请问你用什么办法进行缩小呢? (1)RSL (2)Module (3)外部加载资源

2、做一个flex项目,你认为成功的要素在哪呢? (1)数据和需求等传统软件项目的成功要素 (2)模块化开发,MVC框架 (3)swf文件减肥,运行效率,内存泄露问题,前台优化 (4)开源组件的使用

3、flex 前端的性能优化 (1)、避免容器的多级嵌套,减少相对尺寸、相对定位的使用。 (2)、尽量使用轻量级的容器 (3)、避免使用大体积的组件,比如DataGrid、AdvancedDataGrid (4)、处理数据时多用分页的方式 (5)、少使用setStyle (6)、使用延迟实例化加载子组件

4.Embed绑定图片有什么缺点? 答:直接编译到swf文件中,造成其体积过大。而且由于嵌入代码中,维护不便。

5、flex里调用JS措施? 答:直接在AS中利用ExternalInterface.call()来调用JS措施。如: import flash.external.ExternalInterface ; ExternalInterface.call(“JSFunction”); ExternalInterface.call(“JSFunctionWithParameters”,”myParameter”); var result:String=ExternalInterface.call(“JSFunctionWithReturn”); 6、用JavaScript调用ActionScript函数 答:利用ExternalInterface.addCallback在JavaScript里设置对Flex的回调措施并且在JavaScript里调用ActionScript措施。 AS: ExternalInterface.addCallback(“function1”,callback1); privatefunctioncallback1():void { Alert.show(“callback1executed”); } JS: container[swf].function1(); 6、FileReference browse(typeFilter:Array = null):Boolean//揭示一个文件博览对话框,让用户抉择要上载的文件。 cancel():void//废止正在对该 FileReference 对象厉行的任何上载或下载垄断。 download(request:URLRequest, defaultFileName:String = null):void//敞开对话框,以批准用户从长途服务器下载文件. upload(request:URLRequest, uploadDataFieldName:String = “Filedata”, testUpload:Boolean = false):void//开始将用户抉择的文件上载到长途服务器。

7、flash与flex是如何调停开发的? 答:这个问题能够这么来会意,万一是确乎必需用到FLEX SDK的利用,那我们就能够发生一个flex工程,翔实必需flash做UI的时候,输出成swc作为flex的skin,万一说并无须要flex sdk,只是为了编码得体而抉择flex的话,那我们凡是发生一个as工程,让flex作为flash的编码器。

8、请说下事件里的currentTarget 和 target的区别? 答:在事件流的过程中,目标阶段确定的目标对象由Event中的target属性来记录, 冒泡阶段移动的游标则由currentTarget来记录。事件对象冒泡过程中每往上移动一级,就会克隆出一个仅与前副本currentTarget不同的新副本。

9、warning: unable to bind to property ” on class ‘Object’ (class is not an IEventDispatcher) 在使用ItemRender时,经常会出现这种警告? 答:ArrayCollection的子元素是无法作为数据源绑定的。可以声明中间变量,在override set data时将ArrayCollection的子元素传入, 然后再将中间变量作为新的绑定源即可。

10、常用的几个切换数据的组件比如: TabNavigator等都有属性 creationPolicy 你知道这种策略的使用方式是什么嘛?以及优,缺点呢? 答:延迟实例化。优点是可以更快地加载组件,缺点是首次访问其他组件时,由于需要重新加载此组件,可能会有一定的延迟。

11、请试写一个自定义的验证组件 答:

package myCompenent
    {
        import mx.validators.Validator;//引用Validator类
        import mx.validators.ValidationResult;//引用ValidationResult类
        public class myValidators extends Validator
        {
            public function myValidators()//构造函数
            {
                super();
            }
            private var results:Array;//定义一个数组,用以存储错误
            //重写验证函数
            override protected function doValidation(value:Object):Array
            {
                var s:String = value as String;
                results = [];//清空数组
                results = super.doValidation(value);//先用继承类中的doValida tion方法验证
                if (results.length &gt; 0)//如果验证时有错,返回错误信息
                    return results;
                if(s.length&gt;6)//自定义验证,字符长度不超过6
                {
                    //记录出错信息
                    results.push(new ValidationResult(true,”text”,”StringTooLong”, “字符长度超过6了”));
                }
                return results;
            }
        }
    } 

在flex中监听鼠标右键事件,提示 TypeError Error 2007 参数type不能为空。

2013-03-11 Flash

在flex中监听鼠标右键事件 ,报错,提示 缺少参数、

TypeError: Error 2007: 参数 type 不能为空。

at flash.events::EventDispatcher/addEventListener()
at com.waylau.eagleos.components::DesktopExplorer/service_resultHandler()[D:\workspaceFB47\com.waylau.eagleos_0.9.5\src\com\waylau\eagleos\components\DesktopExplorer.mxml:59]
at com.waylau.eagleos.components::DesktopExplorer/__service_result()[D:\workspaceFB47\com.waylau.eagleos_0.9.5\src\com\waylau\eagleos\components\DesktopExplorer.mxml:214]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at HTTPOperation/http://www.adobe.com/2006/flex/mx/internal::dispatchRpcEvent()[E:\dev\4.y\frameworks\projects\rpc\src\mx\rpc\http\HTTPService.as:993]
at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::resultHandler()[E:\dev\4.y\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:318]
at mx.rpc::Responder/result()[E:\dev\4.y\frameworks\projects\rpc\src\mx\rpc\Responder.as:56]
at mx.rpc::AsyncRequest/acknowledge()[E:\dev\4.y\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:84]
at DirectHTTPMessageResponder/completeHandler()[E:\dev\4.y\frameworks\projects\rpc\src\mx\messaging\channels\DirectHTTPChannel.as:451]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()

据悉,flash player 11.2版本以后支持鼠标右键,

所以开发的项目中运行时版本要相应设置,增加参数 -swf-version=15 以支持右键 ,即可


Flex/AS3/flash player支持屏蔽右键菜单,自定义菜单,并设置相应的菜单事件(示例,图解)

2013-03-04 Flash Flex

Flex/AS3/flash player支持屏蔽右键菜单,自定义菜单,并设置相应的菜单事件(示例,图解)

播放器 版本 11.2以后支持右键菜单屏蔽及自定义菜单 1.更新播放器 ,11.2 以上版本

http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_3.swc
http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_4.swc
http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_2.swc
http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_5.swc

2.编译器参数设置-swf-version=15(见图)

  1. 自定义 菜单,并设置相应的菜单事件 (Flex代码)
<?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"
			   xmlns:twaver="http://www.servasoftware.com/2009/twaver/flex"
			   applicationComplete="init()">
	<fx:Script>
		<![CDATA[

			import mx.controls.Button;
			import mx.controls.Menu;
			import mx.events.MenuEvent;
			import mx.controls.Alert;

			private var menu:Menu = null;
			private var bt:Button = new Button();

			private function init():void {
				bt.label = "走你~";
				network.addElement(bt);
				network.addEventListener(MouseEvent.RIGHT_CLICK,handleRighClick);//监听右键
			}
			private function handleRighClick(e:MouseEvent):void {

				if(menu != null){
					menu.hide();
				}
				menu = Menu.createMenu(network, myMenuData, false);//myMenuData菜单数据源
				menu.labelField = "@label";//右键菜单的文字

				var point:Point = network.globalToLocal(new Point(e.stageX, e.stageY));
				menu.show(point.x, point.y);
				menu.addEventListener(MenuEvent.ITEM_CLICK,menuItemClickHandler);  //菜单事件
			}

			private function menuItemClickHandler(evt:MenuEvent):void{
				Alert.show(evt.item.@eventName)  //将事件名显示出来
			}
		]]>
	</fx:Script>
	<fx:Declarations>
		<fx:XML id="myMenuData">
			<root label="MenuItem 1" >
				<menuitem label="new" eventName="new" />
				<menuitem label="refreash" eventName="refreash" />
				<menuitem label="remove" eventName="remove" />
			</root>

		</fx:XML>
	</fx:Declarations>
	<s:Group id="network" width="100%" height="100%"  />
</s:Application>


可行性分析与需求分析

2013-02-27 Management Design

一、概念

可行性分析——可干否 需求分析——要干啥(避免需求蔓延) 二、可行性分析

柳传志“三不干”:没钱赚的事我们不干;有钱赚但投不起钱的事不干;有钱赚也投得起钱但没有可靠的人选,这样的事也不干。 可行性分析要素:经济、技术、社会环境、人 (1) 经济:成本——收益分析、短期——长远利益分析

(2) 技术:技术熟悉度、成熟度、可靠性、稳定性、技术成本、学习曲线

(3) 社会环境:市场、法律、道德

(4) 人——“人物,人才,人手,人渣。”最好的分工是让“人物”当领导,“人才”做第一线的开发人员,“人手”做行政人员,“人渣”负责行贿。

可行性分析报告(附录1) 三、需求分析

难点:客户说不清、需求老变更、理解有偏差 过程: 3.方式:

(1) 研究用户

(2) 调查问卷

(3) 原型完善

(4) 用户陈述

4.需求规格说明书(附录2)

附录1(可行性分析报告)

1.引言

1.1 编写目的

阐明编写可行性研究报告的目的,描述报告基本组成要素,指出读者对象。

1.2 项目背景

列出拟开发软件系统的名称,项目委托者、开发者和预期用户,说明该软件系统与其他系

统之间的关系等。

1.3 定义

列出报告中所使用的专门术语的定义和缩写词的原意。

1.4 参考资料

列出本文档需要引用的参考资料的来源。包括:已被批准的项目任务书、合同或上级机关

批文,与项目有关的已经公开发表的论文、著作,需要采用的标准或规范。

2.可行性研究的前提

2.1 基本要求

列出项目的各项基本要求,涉及功能、性能、数据输入、数据输出、数据处理流程、安全

保密要求、与其他系统的关系、完成期限等。

2.2 基本目标

涉及人力与设备费用的减少,工作环境的改善,工作效率的提高,处理速度、控制精度或

生产能力的提高,信息管理服务的改进,自动决策功能的改进等。

2.3 条件、假定和限制

涉及拟开发系统运行寿命的最小值,项目经费来源与限制,政策和法规方面的限制,硬件、

软件、开发环境和运行环境方面的条件与限制,可以利用的相关资源,拟开发系统要求投入使

用的最迟时间等。

3.对现有系统的分析

3.1 系统模型

可使用系统方框图、系统流程图说明现有系统的基本构造与基本处理流程。

3.2 工作负荷

列出现有系统所承担的工作与工作量。

3.3 费用支出

涉及现有系统运行过程中的人力、设备、空间、支持性服务和材料等各项支出。

3.4 局限性

指出现有系统存在的问题,并说明开发新系统或改造现有系统的必要性。

B.2 项目计划说明书209

4.对拟开发系统的分析

4.1 拟开发系统的体系结构

可使用系统方框图对拟开发系统的体系结构进行概要描述。

4.2 拟开发系统的工作模型

可使用系统流程图说明拟开发系统的基本处理流程。

4.3 拟开发系统的优越性

将拟开发系统与现有系统进行对比,并在诸如提高处理能力、减轻工作负荷、增强系统灵

活性和保证数据安全等方面,说明拟开发系统所具有的优越性。

4.4 拟开发系统可能带来的影响

涉及拟开发系统将对硬件设备、软件配置和用户操作等方面带来的影响。

5.对拟开发系统的可行性评价

5.1 技术可行性评价

说明拟开发系统在技术方面具备的可行性,例如,在当前技术允许的条件下,该系统的功

能目标能否达到;在规定的时间期限内,该系统的开发能否按期完工。

5.2 经济可行性评价

说明拟开发系统所需的开发费用和可以预期的经济收益,并由此进行成本效益分析。

5.3 社会因素的可行性评价

从法律法规、用户操作规程等方面进行可行性评价,例如项目合同中责任是否明确,拟开

发系统是否存在著作侵权,是否侵犯了国家、集体或他人的利益,拟开发系统是否充分考虑到


Cairngorm框架项目开发流程

2013-02-26 Cairngorm Flex

##Cairngorm框架的流程,由前往后 ,如下:

###Services.mxml

###VO ###model ###注册model

###event // 常量值简短,有利于编译效率 ###DL ###command

###AppControl

###view


软件工程概述

2013-02-20 Management

一、软件工程概述

软件工程是一门研究用工程化方法构建和维护有效的、实用的和高质量的软件的学科。

最主要的目的是为了解决软件危机。

 

二、软件危机

表现:

1.软件开发成本、进度的估计很不准确

软件开发机构制定的项目计划跟实际情况有很大差距,使得开发经费一再突破。由于对工

作量和开发难度估计不足,进度计划无法按时完成,开发时间一再拖延,这种现象严重降低了软件开发机构的信誉。

2.软件产品常常与用户的要求不一致

在开发过程中,软件开发人员和用户之间缺乏信息交流。开发人员常常是在对用户要求只

有模糊了解的情况下就仓促上阵,匆忙着手编写程序。由于这些问题的存在,导致开发出来的软件不能满足用户的实际应用需要。

3.软件产品质量可靠性差

软件开发过程中,没有建立起确实有效的质量保证体系。一些软件项目为了赶进度或降低

软件开发成本,甚至不惜降低软件质量标准、偷工减料。

4.软件文档不完整、不一致

计算机软件不仅仅是程序,在软件开发过程中还应该产生出一系列的文档资料。实际上,

软件开发非常依赖这些文档资料。在软件开发过程中,软件开发机构的管理人员需要使用这些文档资料来管理软件项目;技术人员则需要利用文档资料进行信息交流;用户也需要通过这些文档资料来认识软件,对软件进行验收,熟悉软件的安装、操作等。但是,由于软件项目管理工作的欠缺,软件文档往往不完整,对软件的描述经常不一致,很难通过文档去跟踪软件开发过程中软件产品规格的变更。

5.软件产品可维护性差

软件中的错误非常难改正,软件很难适应新的硬件环境,很难根据用户的需要在原有软件

中增加一些新的功能。这样的软件是不便于重用的,以前开发的软件,一旦过时就不得不完全丢弃。

6.软件生产率低

软件生产率跟不上硬件的发展速度,不能适应计算机应用的迅速普及,以致现代计算机硬

件提供的巨大潜力不能被充分利用。

 

三、危机产生的原因

看点历史:

观察软件的发展,可以发现软件生产有三个发展时代,即程序设计时代、程序系统时代和

软件工程时代。

1.程序设计时代(20 世纪50 年代)

这个时期的程序大多是自用,程序的编写者往往也就是使用者,软件还没有形成为产品。

由于早期程序大多是为某个具体应用而专门编写的,程序任务单一,因此,对程序的设计也就仅仅体现在单个程序的算法上。早期程序还往往只能在某台专门的计算机上工作,很难将程序由一台设备移植到另一台设备。

 

2.程序系统时代(20 世纪60 年代)

这个时期的软件开发更多地依赖于个人创作。由于软件开发的主要内容仍然是程序编写,

软件开发的核心问题仍是技术问题;于是,用户的意图被忽视了,除了程序之外的其他文档、

技术标准、软件在今后运行过程中的维护等问题,也往往被忽视了。

软件已经开始成为产品,但软件的生产方式则是跟产品并不适宜的作坊创作方式。于是,

随着软件规模的不断扩大,软件危机现象在这个时期最终爆发出来。

 

3.软件工程时代(20 世纪70 年代起)

1968 年在联邦德国召开的计算机国际会议上,专门针对软件危机问题进行了讨论,在这次

会议上正式提出并使用了“软件工程”术语。于是,软件工程作为一门新兴的工程学科诞生了。

在软件开发上,自20 世纪70 年代以来的30 年里,结构化的工程方法获得了广泛应用,

并已成为了一种成熟的软件工程方法学;而自20 世纪90 年代起,基于面向对象的工程方法,也已被应用于软件开发之中。应该说,采用工程的原理、技术和方法实施软件产品开发,以适应软件产业化发展的需要,成为了这个时期诸多软件企业的追求目标。

 

 

真正的原因:

1.软件的不可见特性

软件不同于硬件,它是计算机系统中的逻辑部件,缺乏“可见性”。硬件错误往往可以通

过它的物理现象直接反映出来,例如,出现不正常的发热、噪音现象等;但软件错误没有这些直观表现,例如,软件中存在的程序行错误,就必须等到这行程序执行时才有可能被发现。因此,软件错误比起硬件错误来更难发现。软件的不可见特性也使得对软件项目的量化管理更难实施,对软件质量的量化评价更难操作。

2.软件系统规模庞大

软件成为产品以后已不同于早期程序,随着它的功能的增多,其规模、复杂程度越来越大。

例如,1968 年美国航空公司订票系统达到30 万条指令;IBM360OS 第16 版达到100 万条指令;1973 年美国阿波罗计划达到1 000 万条指令。这些庞大规模的软件系统,其复杂程度已超过了人所能接受的程度;但是,面对不断复杂的软件系统,其开发手段却仍然需要依靠开发人员的个人创造与手工操作。

3.软件生产工程化管理程度低

软件生产的工程化管理是软件作为产品所必须的,这意味着软件也需要像硬件一样,在软

件分析、设计完成之后,才能考虑软件的实现。应该说,工程化管理能够降低解决问题的代价。但是,许多软件的开发则往往是在分析、设计没有完成的情况下,就已经进入编码实现阶段。由于前期准备工作不充分,致使软件项目管理纷乱,严重影响软件项目成本、开发进度。

4.对用户需求关心程度不够

软件开发机构不熟悉用户业务领域。软件技术人员所关注的仅仅是计算机技术,它们不太

愿意和用户沟通,轻视对用户的需求调查,也缺乏有效的用户调查策略、手段。由于这些问题的存在,使得用户的需求意愿不能充分反映,或被错误理解。

实际上,软件是为用户开发的,只有用户才能真正了解他们自己的需要。由于没有对用户

做大量深入细致的调查研究,以致软件需求规格定义不准确,并最终使得完成后的软件不能适应用户的应用需要。

5.对软件维护重视程度不够

软件开发缺乏统一的规范。在软件产品开发过程中,开发者很少考虑到这个软件今后还需

要提供维护。但是,软件的使用周期漫长,软件错误具有隐蔽性,许多年之后软件仍可能需要改错。另外,软件的工作环境也可能会在几年后发生改变;用户也可能在软件运行几年以后,要求对它增加新的功能。这些都是属于软件维护问题。实际上,软件的可维护性是衡量软件质量的一项重要指标,软件可维护性程度高,软件就便于修正、改版和升级,由此可以使软件具有更长的使用寿命。

6.软件开发工具自动化程度低

尽管软件开发工具比30 年前已经有了很大的进步,但直到今天,软件开发仍然离不开工

程人员的个人创造与手工操作,软件生产仍不可能像硬件设备的生产那样,达到高度的自

动化。

 

四、探讨如何解决危机

  1. 软件工程的主要环节有:人员管理、项目管理、可行性与需求分析、系统设计、程序设计、测试、维护

 

 

  1. 常见的软件工程模型有:线性模型(瀑布模型),渐增式模型,螺旋模型,快速原型模型,增量模型,喷泉模型等

最早出现的软件工程模型是线性模型(又称瀑布模型)。

瀑布模型核心思想是按工序将问题化简,将功能的实现与设计分开,便于分工协作,即采用瀑布模型用结构化的分析与设计方法将逻辑实现与物理实现分开。将软件生命周期划分为制定计划、需求分析、软件设计、程序编写、软件测试和运行维护等六个基本活动,并且规定了它们自上而下、相互衔接的固定次序,如同瀑布流水,逐级下落。

002

优点

1)为项目提供了按阶段划分的检查点。

2)当前一阶段完成后,您只需要去关注后续阶段。

缺点

1)在项目各个阶段之间极少有反馈。

2)只有在项目生命周期的后期才能看到结果。

3)通过过多的强制完成日期和里程碑来跟踪各个项目阶段。

4)瀑布模型的突出缺点是不适应用户需求的变化.

 

线性模型太理想化,太单纯,已不再适合现代的软件开发模式,几乎被业界抛弃。但是复杂的“非线性”问题时,总是千方百计地将其分解或转化为一系列简单的线性问题。

 

 

螺旋模型:

基本做法是在“瀑布模型”的每一个开发阶段前引入一个非常严格的风险识别、风险分析和风险控制,它把软件项目分解成一个个小项目。每个小项目都标识一个或多个主要风险,直到所有的主要风险因素都被确定。

003

优点

1)设计上的灵活性,可以在项目的各个阶段进行变更。

2)以小的分段来构建大型系统,使成本计算变得简单容易。

3)客户始终参与每个阶段的开发,保证了项目不偏离正确方向以及项目的可控性。

4)随着项目推进,客户始终掌握项目的最新信息 , 从而他或她能够和管理层有效地交互。

5)客户认可这种公司内部的开发方式带来的良好的沟通和高质量的产品。

缺点

很难让用户确信这种演化方法的结果是可以控制的。建设周期长,而软件技术发展比较快,所以经常出现软件开发完毕后,和当前的技术水平有了较大的差距,无法满足当前用户需求。

螺旋模型的项目适用:

对于新近开发,需求不明确的情况下,适合用螺旋模型进行开发,便于风险控制和需求变更!

 

快速原型模型


Linux(Ubuntu)下设置golang环境变量

2013-01-31 Golang

1).源代码安装go语言

Go的工具链采用C语言编写,要构建它,你需要安装一个C编译器,本例采用gcc工具; 进入linux 终端,输入命令行

sudo apt-get install build-essential

Go使用Mercurial进行版本管理,首先你必须安装了Mercurial,对于 Ubuntu/Debian 系统先安装easy_install;

sudo apt-get install mercurial

出现Processing triggers for python-support…需先安装python环境 执行

sudo apt-get install python-setuptools python-dev

sudo easy_install mercurial

如果 还不行,那直接下载Mercurial安装

获取GO代码

hg clone -r release https://go.googlecode.com/hg/ $GOROOT

安装Go:

cd $GOROOT/src

./all.bash

如果 还不行,那直接下载编译好的代码安装 解压 go包放用户根目录下

sudo tar zxvf ~/Downloads/go1.0.3.linux-386.tar.gz -C /opt

2).设置环境变量,在/etc/profile文件同添加以下内容

sudo gedit /etc/profile

export GOROOT=$HOME/go
export GOBIN=$GOROOT/bin
export GOARCH=386
export GOOS=linux
export GOPATH=$HOME/workspacego
export PATH=.:$PATH:$GOBIN

GOARCH、GOOS为可选配置,交叉编译时有用 GOPATH设置工作空间,允许多个目录,当有多个目录时,用分隔符分隔,当有多个GOPATH时,默认会将go get的内容放在第一个目录下;

$GOPATH 目录约定有三个子目录:

src 存放源代码(比如:.go .c .h .s等)

pkg 编译后生成的文件(比如:.a)

bin 编译后生成的可执行文件(为了方便,可以把此目录加入到 $PATH 变量中)

应用刚刚配置的环境变量:source /etc/profile

上面的配置是针对系统级别的,建议采用用户级别的配置如下:

如果用户根目录下不存在.bash_profile,则

cat > .bash_profile

export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=$HOME/workspacego

CTRL_D(这是按 CTRL - D两个键同时)

每次启动系统应用

. ./.bash_profile

官方建议把配置记录在用户在~/.bashrc或者 ~/.profile中,这样 登陆就可以使用go 而不用,每次登陆系统都要执行. ./.bash_profile

配置文件的区别,请参阅后面的附录

3).查看go是否是release版

hg identify

更新go到新版本

cd $GOROOT

hg pull

hg update release

./all.bash

4).浏览本地doc

在命令行执行

godoc -http=:8080

在浏览器地址输入:http://127.0.0.1:8080,即可进入doc界面

5).搭建基于浏览器的交互式Go编程指南-gotour

5.1).安装Go语言英文教程:

sudo go get code.google.com/p/go-tour/gotour

5.2).安装Go语言中文教程:

sudo go get bitbucket.org/mikespook/go-tour-zh/gotour

在命令行执行gotour,在浏览器地址输入:http://127.0.0.1:3999,即可进入教程的学习界面。

附录

参考:http://blog.csdn.net/wumingxing0228/article/details/6050175

环境变量是和Shell紧密相关的,用户登录系统后就启动了一个Shell。对于Linux来说一般是bash,但也可以重新设定或切换到其它的 Shell。对于UNIX,可能是CShelll。环境变量是通过Shell命令来设置的,设置好的环境变量又可以被所有当前用户所运行的程序所使用。对于bash这个Shell程序来说,可以通过变量名来访问相应的环境变量,通过export来设置环境变量。下面通过几个实例来说明。

1)etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. 并从/etc/profile.d目录的配置文件中搜集shell的设置. 注:在这里我们设定是为所有用户可使用的全局变量。

2)/etc/bashrc:为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取.

3)~/.bashprofile:每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件. 注:~在LINUX下面是代表HOME这个变量的。 另外在不同的LINUX操作系统下,这个文件可能是不同的,可能是~/.bashprofile; ~/.bash_login或 ~/.profile其中的一种或几种,如果存在几种的话,那么执行的顺序便是:~/.bashprofile、 ~/.bashlogin、 ~/.profile。比如我用的是Ubuntu,我的用户文件夹下默认的就只有~/.profile文件。

4)~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取. (注:这个文件是 .开头的,所以在文件夹中被隐藏了) 那么我们如何添加自己定义的环境变量呢? 用记事本打开这个文件,然后在里面最后写上: xiaokang=kangkang 然后保存,这样每次打开一个新的terminal的时候,我们这个变量就生效了。记住,如果你已经打开一个terminal,然后你修改了这个文件,那么在这个terminal下是不会生效的。一般情况用户最好在这里进行修改,但是有时候会覆盖父级的变量,比如PATH是ROOT设定的,但是如果你在这个文件里面写了PATH=xx,那么将来所有的PATH都成了xx了,所以我们应该在这个文件中写为: PATH=$PATH:xx 这样就把原来的和你自己的一起加上了。而且注意在LINUX系统下用:分割表示并列,而不是windo的; 3和4都是在用户目录下的,他们唯一的不同是: .bash_profile只能在登录的时候启动一次。在我的Ubuntu里面这个3文件似乎没有。

5)~/.bash_logout:当每次退出系统(退出bash shell)时,执行该文件. 另外,/etc/profile中设定的变量(全局)的可以作用于任何用户,而~/.bashrc等中设定的变量(局部)只能继承/etc/profile中的变量,他们是/”父子/”关系.

~/.bash_profile 是交互式、login 方式进入 bash 运行的 ~/.bashrc 是交互式 non-login 方式进入 bash 运行的 通常二者设置大致相同,所以通常前者会调用后者。

好的,总结一下他们的执行方式: 当你登录并且登录shell是bash时,bash首先执行/etc/profile文件中的命令(如果该文件存在),然后它顺序寻找~ /.bashprofile,~/.bashlogin或~/.profile文件,并执行找到的第一个可读文件中的命令.当登录bash退出时,它 将执行~/.bashlogout文件中的命令. 当启动一个交互的bash时,它将执行~/.bashrc文件中的命令(如果该文件存在并且可读).当非交互地启动以运行一个shell脚本时,bash将查找bashenv环境变量,确定执行文件的名称.



Go For Java Programmers(面向Java开发者的GO编程)

2013-01-13 Golang Java

本文旨在帮助JAVA开发者迅速掌握 Go语言.

开始用一个很容易能被所有的Java程序员认出的例子来突出特色,然后对GO的框架给出了详细的的描述,最后用一个例子来说明GO结构中没有与 Java直接对应处。

##Hello stack (一个栈的例子) 为了吊起你的胃口,我们用一个麻雀虽小,五脏俱全和符合习惯的例子对应这个Stack.java 程序


// 包collection实现了生成栈.
package collection

// 零值栈是一个空栈,准备被使用.
type Stack struct {
    data []interface{}
}

// Push函数将x添加到栈顶.
func (s *Stack) Push(x interface{}) {
    s.data = append(s.data, x)
}

// Pop函数是将栈顶元素移除并返回.
// 在Pop函数执行在空栈时,会被一个运行时的error警示.
func (s *Stack) Pop() interface{} {
    i := len(s.data) - 1
    res := s.data[i]
    s.data[i] = nil  // 避免内存泄露
    s.data = s.data[:i]
    return res
}

// Size函数返回栈中元素的个数
func (s *Stack) Size() int {
    return len(s.data)
}

stack.go

  • 顶级声明出现之前,直接的评论是文档注释。他们是纯文字。.
  • 对于声明,你把名字写在类型后面.
  • struct 对应Java中的类, 但struct组成不是方法而只能是变量.
  • Tinterface{}类型对应Java的 Object. 在GO中它被所有的类型所实现,而不仅仅是引用类型.
  • 代码段 (s *Stack) 声明了一个方法,接收者 s 对应Java中的 this.
  • 操作符:=声明并初始化了一个变量. 它的类型可以从初始化表达式中推导出.

这里是一个的Hello world程序,演示了如何使用collection.Stack的抽象数据类型.


package collection_test

import (
    collection "."
    "fmt"
)

func Example() {
    var s collection.Stack
    s.Push("world")
    s.Push("hello, ")
    for s.Size() > 0 {
        fmt.Print(s.Pop())
    }
    fmt.Println()
    //输出: hello, world
}

example_test.go

##概念上的差异

  • Go的构造器没有类。Go 用 structs 和 interfaces来替代实例化方法,类的继承机制,动态方法查找.也可用于Java使用泛型接口
  • Go提供所有类型的指针的值,而不只是对象和数组。对于任何类型 T,有一个相应的指针类型*T表示指针指向类型 T的值。 offers pointers to values of all types, not just objects and arrays.
  • Go允许任何类型都有方法而没有装箱的限制 allows methods on any type; no boxing is required. 方法receiver,在Java中对应this可以是直接值或者是指针.
  • 数组在Go就是值. 当一个数组被当做函数的参数时,这个函数接收到的是数组的拷贝而不是它的指针. 然而在实践中,函数经常使用 slices作为参数; slices引用了基础数组.
  • 该语言提供了字符串,一个字符串行为就像一个字节片,但是是不可改变的。
  • 该语言中的哈希表被称作maps.
  • 该语言提供了独立运行的线程goroutines 和他们之间的通信渠道channels.
  • 某些类型(maps, slices, 和 channels)是按引用传递,而不是值。也就是说,传递一个map到函数并而不是拷贝map,如果函数修改了map,将被调用者看到变化。在Java术语来说,可以认为这是一个map的引用.
  • Go提供了两种访问级别对应Java的public和包的private.如果它的命名是大写字母开头就是最高级别public,反之就是包的private.
  • 作为替换Java中的异常机制, Go采用了类型 error值来表示事件,如文件结尾,和运行时的panics来表示运行时的错误,如数组越界等.
  • Go不支持隐式类型转换。混合使用不同类型的操作需要显式转换.
  • Go不支持函数重载。在同一范围内的函数和方法必须具有唯一的名称.
  • Go使用nil表示无效的指针,类似于Java使用null.

##句法 ###声明

声明是跟Java是相反的。你在类型后面再写名称,类型声明从左往右更容易读

Go 与Java相对应的

Go 与Java相对应的
var v1 int int v1;
var v2 *int Integer v2;
var v3 string String v3 = "";
var v4 [10]int int[] v4 = new int[10]; // v4 在Go中是一个值.
var v5 []int int[] v5;
var v6 *struct { a int } C v6; // Given: class C { int a; }
var v7 map[string]int HashMap<String,Integer> v7;
var v8 func(a int) int F v8; // Given: interface F { int f(int a); }

声明的一般形式是一个关键字后面跟着被声明对象的名字.这个关键字是const, type, var, 或者func. 您也可以使用一个关键字,后面的括号中跟着一系列声明.

var (
    n int
    x float64
)

当声明一个函数,你必须提供每个参数的名称,或者不提供任何参数的名称,你不能提供了一些而忽略了另外一些名字。您可以组合几个相同类型的名称:

func f(i, j, k int, s, t string)

一个变量可以在声明时初始化。当这样做时,指定的变量的类型是允许的,但不是必需的。当未指定类型,默认的是初始化表达式的类型.

var v9 = *v2 如果一个变量没有立即初始化,必须要制定类型。那样的情况下,它它会被隐式初始化该类型的零值zero value(0, nil, "", 等.). Go不存在未初始化的变量.

###短声明

在函数中,一个短的声明句法是 := 表示.

v10 := v1 这等效于

var v10 = v1

###函数类型

在Go中,函数都是一等公民。Go的函数类型表示一组所有具有相同的参数和返回类型的函数.

type binOp func(int, int) int

var op binOp
add := func(i, j int) int { return i + j }

op = add
n = op(100, 200)  // n = 100 + 200

###多重分配

GO允许多重分配。在右边的表达式会在评估后,再分配到任何的左操作数。

i, j = j, i  //交换i和j. 函数可以具有多个返回值,表示由括号中的列表。返回的值可以存储分配给一个变??量列表。

func f() (i int, pj *int) { ... }
v1, v2 = f()

###空白标识符

空白标识符提供了一种忽略多值表达式返回值的方式,用下划线字符表示: The blank identifier, represented by the underscore character, provides a way to ignore values returned by a multi-valued expression:

v1, _ = f()  // 忽略f()返回的第二个值.

###分号和格式

为了消除对分号和格式不必要的担忧,你可能会用gofmt程序来写GO风格的标准代码,虽然这种风格看起来很古怪,但熟悉了之后最终会像其他语言风格一样变得舒服

Go的代码在实际中很多出现分号。严格来说,Go所有的声明都用分号结束。但是Go毫无疑问会在每个非空白行的结尾插入一个分号,除非它还没有完. 这样做的后果是,在某些情况下,Go不允许断行。举例,你可能会像下面这样写:

func g()
{            //无效的;“{”应该是在前面那一行。
} 在g()后面会被插入一个分号,这样就使他像是一个函数声明而不是函数定义了类似的,你不能这样写:

if n == 0 {
}
else {       // 无效的; "else {" 应该是在前面那一行。
} 在} 后和else前面会插入一个分号,导致句法错误.

###条件语句

Go在条件语句中并不使用括号,像 if条件语句 , for 条件语句的表达式, switch 条件语句的值. 另一方面,它并不需要在 if或 for条件语句中加花括号

if a < b { f() }
if (a < b) { f() }           // 括号是不必要的.
if (a < b) f()               // 无效的
for i = 0; i < 10; i++ {}
for (i = 0; i < 10; i++) {}  // 无效的

此外, if和switch 接收一个可选的初始化的状态,那么惯用做法是建一个局部变量

if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}

###For 语句

Go没有while和do-while语句. 当for语句的条件比较单一时,他的作用就像是while语句. 完全省略条件则产生一个死循环。

for语句可能包含range遍历 strings, arrays, slices, maps, 或 channels。除了写成下面这样

for i := 0; i < len(a); i++ { ... } 去遍历a的元素,也可以写成

for i, v := range a { ... } 这里的i指索引, v代表的array, slice, 或者string的连续元素。对于字符串,i是一个字节的索引,v指向rune类型(rune类型是int32)的一个别名)。maps迭代产生键 - 值对,而channels只产生一个迭代值。

###Break和continue

像Java一样,GO许可break和continue指定一个标签,但标签上必须指的for, switch, 或者 select 语句.

###Switch 语句

在 switch 语句,case 标签默认情况下不通过,但你可以让他们 fallthrough语句结束的情况下通过了。

switch n {
case 0:  // empty case body
case 1:
    f()  // f is not called when n == 0.
} 但是一个case可以包含过个值

switch n {
case 0, 1:
    f()  // f is called if n == 0 || n == 1.
} case的值可以支持任何类型的相等比较操作符,如字符串或指针。一个丢失表达式的switch语句 等价于表达式为 true。

switch {
case n < 0:
    f1()
case n == 0:
    f2()
default:
    f3()
} ### ++ 和 -- 语句

++和–只能作为后缀操作符,和仅在语句中,而不是在表达式中。例如,你不可以写n = i++。

defer语句

defer语句调用一个函数的执行被推迟到函数返回那一刻。defer语句执行时,被递延的函数的参数被计算,并保存,以备将来使用

f, err := os.Open("filename")
defer f.Close()  // f will be closed when this function returns.

##Constants(常量) GO中的常数可能是untyped的。这适用于无类型的常量表达式的数字文本,和使用const声明的无类型的常量表达式。当它被用在需要一个带类型的值的背景下,一个无类型的常量的可以被转变成有类型的值。这样常量的使用相对自由,即使Go没有隐式类型转换

var a uint
f(a + 1)    // The untyped numeric constant 1 becomes typed as uint.
f(a + 1e3)  // 1e3 is also typed as uint. 语言对非类型化的数字常量不限制大小。限制仅适用于使用一个常量时,其中一种类型是必需的。

const huge = 1 << 100
var n int = huge >> 98 如果是不存在的变量声明的类型和相应的表达式的计算结果为一个非类型化的数字常数,这个常数是被转换为 rune, int, float64, 或者complex128 类型,取决于该值是否一个字符,整数,浮点,或复杂的常数。

c := '?'      // rune (alias for int32)
n := 1 + 2    // int
x := 2.7      // float64
z := 1 + 2i   // complex128 GO 不存在枚举类型。相反,你可以使用特殊的名字iota在单一的const声明中从而得到一系列累加值。当初始化表达式省略为一个 const,它重用了前面的表达式。

const (
    red = iota  // red == 0
    blue        // blue == 1
    green       // green == 2
)

Structs(结构体)

结构体对应于Java中的类,但一个结构的成员不能是方法,而是变量。结构体的指针是类似Java的的引用变量。与Java类不同的是,结构也可以被定义为直接值。在这两种情况下使用 .来访问结构体的成员。

type MyStruct struct {
    s string
    n int64
}

var x MyStruct      // x is initialized to MyStruct{"", 0}.
var px *MyStruct    // px is initialized to nil.
px = new(MyStruct)  // px points to the new struct MyStruct{"", 0}.

x.s = "Foo"
px.s = "Bar" 在Go中,方法可以与任何命名的类型关联,而不仅仅是与结构体。详情见方法和接口的讨论。

##Pointers(指针)

如果你有一个int或struct或者array需要分配对象的内容复制。 想达到Java的引用变量的效果,Go使用指针。对于任何类型e T,有一个相应的指针类型*T,表示指针类型 T的值

给指针变量分配存储空间,使用内置函数new,传入一个类型,并返回一个指针,指向分配的存储空间。分配的空间将被零初始化的类型。例如, new(int) 分配存储为一个新的int,初始化它的值为e 0,并返回它的地址,类型 *int。

Java代码T p = new T(),其中 T是一个两个int型实例变量a和b的类,对应于

type T struct { a, b int }
var p *T = new(T) 或者习惯性这样干

p := new(T) var v T代表声明,声明了一个变量包含一个值类型 T,这在Java中是没有的。也可使用复合方式创建并初始化值。

v := T{1, 2} 等同于

var v T
v.a = 1
v.b = 2 对于类型T的操作数x,地址运算符 &x提供值类型为*T的x的地址,

##Slices(切片) slice是概念上一个结构包含三个域:一个数组的指针、长度和容量。切片支持[]操作符来访问底层数组的元素。内置的len函数返回的切片长度。内置的的cap函数返回切片的能力。

给定一个数组,或另一个切片,通过a[i:j]来创建一个新的切片。这个新创建的切片指向a,从索引i开始,并结束索引j之前。它的长度是j - i。如果i 被省略,切片从0开始。如果j 被省略,切片在 len(a)结束。新切片跟 a一样指向相同的数组。即,改变后组成的新的切片的元素在a都能见到。新切片的容量就是简单的a减去i。数组的容量就是数组的长度。

var s []int
var a [10]int

s = a[:]  // short for s = a[0:len(a)] 如果你创建一个值类型为[100]byte(100个字节,也许是一个缓冲区的数组),你想不复制它,而将它传递给函数,那么函数的参数声明类型[]byte,并传入数组的切片。切片也可以用 make的函数创建(如下文所述)。

切片组合采用内置的append函数,Java的ArrayList提供相同的功能。

s0 := []int{1, 2}
s1 := append(s0, 3)      // append a single element
s2 := append(s1, 4, 5)   // append multiple elements
s3 := append(s2, s0...)  // append a slice 切片语法,也可以使用在字符串上。它返回一个新字符串,其值是原始的字符串的子串

##make函数 Map and channel values must be allocated using the built-in function make. For example, calling map和channel值必须使用内置的函数make。例如,调用

make(map[string]int) map[string]int返回一个新分配的值类型。相对于new, make 返回的是实际的对象,而不是一个地址。这是一致的事实,map和channel是引用类型。

对于map,make函数将容量作为一个可选的第二个参数的提示。对于channel,有一个可选的第二个参数来设置channel的缓冲能力,默认为0(无缓冲)。

make函数也可以用来分配一个切片。在这种情况下,它分配内存给基本数组并返回一个引用他的切片。该切片中的元素数是一个必需的参数。第二个可选的参数是切片的容量。

m := make([]int, 10, 20)  // Same as new([20]int)[:10]

##方法和接口 ###方法

方法看起来像一个普通的函数定义,但它有一个receiver(接收者)。receiver是类似Java实例方法中的this引用。

type MyType struct { i int }

func (p *MyType) Get() int {
    return p.i
}

var pm = new(MyType)
var n = pm.Get() 这声明了一个方法Get与MyType关联的。receiver被命名为p 在函数体内。

命名的类型来定义方法。如果您转换不同类型的值,新的值将有新的类型,而不是那些旧的类型。

你可以定义一个内置类型的方法,用新的命名类型声明。新的类型和内置的类型是不同的。

type MyInt int

func (p MyInt) Get() int {
    return int(p)  // The conversion is required.
}

func f(i int) {}
var v MyInt

v = v * v          // The operators of the underlying type still apply.
f(int(v))          // int(v) has no defined methods.
f(v)               // INVALID

###接口

Go接口类似于Java接口,但可被视为一个实现该接口提供任何类型的在Go接口命名的方法。明确的声明是不必要的。

接口像这样:

type MyInterface interface {
    Get() int
    Set(i int)
} 自从 MyType 已经有了Get 方法, 我们可以让 MyType满足接口通过添加

func (p *MyType) Set(i int) {
    p.i = i
} 现在任何只要将MyInterface当做参数就可以接收类型是*MyType的变量

func GetAndSet(x MyInterface) {}

func f1() {
    var p MyType
    GetAndSet(&p)
} 在Java术语,给MyType 定义 Set和Get 使MyType自动实现了MyInterface接口。这种类型型可满足多个接口。这是一种形式的鸭子类型。

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” James Whitcomb Riley

###匿名域

匿名域可以用于实现很像一个Java子类的东西。

type MySubType struct {
    MyType
    j int
}

func (p *MySubType) Get() int {
    p.j++
    return p.MyType.Get()
}
MySubType有效实现的像是MyType的子类型.

func f2() {
    var p MySubType
    GetAndSet(&p)
} Set方法是继承自MyType的,因为关联了匿名域的方法的变为了封闭类型的方法。在这种情况下,因为 MySubType有一个匿名与域 MyType类型,所以为 MyTypee的方法也成为MySubType的方法。Get方法被重写,Set方法被继承。

这是与Java中的子类不完全相同。当一个匿名域的方法被调用时,它的 receiver就是这个匿名域,而不是周围的结构体。换句话说,匿名域上的方法的不会动态调度。当你想要实现相当于Java的动态方法查找,请使用接口。

func f3() {
    var v MyInterface

    v = new(MyType)
    v.Get()  // Call the Get method for *MyType.

    v = new(MySubType)
    v.Get()  // Call the Get method for *MySubType.
}

###类型断言

使用一个类型断言可以使具有一个接口类型的变量转换成具有不同的接口类型。这是在运行时动态执行。与Java不同,并不需要任何声明两个接口之间的关系。

type Printer interface {
    Print()
}

func f4(x MyInterface) {
    x.(Printer).Print()  // type assertion to Printer
} 转换为Printer 完全是动态的。只要x(x中存储的值的实际类型)的 动态类型 定义了一个Print方法。

##Errors(错误机制) Go的多值的返回可以很容易地沿着正常的返回值返回详细的错误消息。按照惯例,这样的error类型的消息,就像下面的简单的内置接口

type error interface {
    Error() string
} 例如,os.Open函数当它无法打开文件时返回一个非零error值。

func Open(name string) (file *File, err error) 以下代码使用 os.Open打开一个文件。如果 error发生,它调用 log.Fatal打印错误信息并停止。

f, err := os.Open("filename.ext")
if err != nil {
    log.Fatal(err)
}
// do something with the open *File f error的接口只需要一个 Error的方法,但具体的error的实现往往有额外的方法,允许调用者进行检查错误的详细信息

##Panic and recover(恐惧和恢复) panic(恐慌)是一个运行时错误,展开goroutine的堆栈,一路运行任何递延的功能,然后停止程序。恐慌与Java异常相似,但只适用于运行时的错误,如一个nil 指针或试图索引数组越界。 Go程序使用内置的error类型 (详见上文)为了表示如文件结束等事件。

可以使用内置的recover (恢复),重新获得控制权的恐慌的goroutine和恢复正常运行。呼叫recover停止展开,并返回传入的参数panic。因为只有运行的未展开代码,内部含有延迟函数,recover只在内递延的函数有效。如果的goroutine是没有恐慌,recover返回nil。

##Go的线程机制和管道 ###Goroutines(Go的线程机制)

Go允许用go开启一个新的执行线程–goroutine。它运行在不同的,新创建的的goroutine中。在一个程序中的所有goroutine共享相同的地址空间。

Goroutines是轻量级的,只占用比堆栈分配多一点的空间。堆栈开始小和成长的分配和释放堆(heap)的要求。内部goroutines像进行了复用多个操作系统线程的协程。您不必担心这些细节。

go list.Sort()  // Run list.Sort in parallel; don’t wait for it. Go处理文字的函数,可以作为结束,在处理go时很强大

func Publish(text string, delay time.Duration) {
    go func() {
        time.Sleep(delay)
        fmt.Println(text)
    }()  // Note the parentheses. We must call the function.
} 变量text和delay在周围函数和函数文字之间共享;只要它们都可以访问,它们就存在。

###Channels(管道)

管道通过指定的元素类型的值来提供两个goroutine同步执行和沟通的机制。 <- 操作符指定通道的方向,发送或接收。如无任何指示方向时,通道是双向的。

chan T          // can be used to send and receive values of type T
chan<- float64  // can only be used to send float64s
<-chan int      // can only be used to receive ints 管道是一个引用类型,用make分配。

ic := make(chan int)        // unbuffered channel of ints
wc := make(chan *Work, 10)  // buffered channel of pointers to Work

To receive a value on a channel, use it as a unary operator. 使用<- 作为一个二元操作符来在管道上发送值。当在管道上接收一个值时,把它作为一元运算符。

ic <- 3       // Send 3 on the channel.
work := <-wc  // Receive a pointer to Work from the channel. 如果管道是无缓冲,那么发送者阻塞,直到接收器接收到值。如果管道有一个缓冲区,发送者阻塞,直到该值已被复制到缓冲区。如果缓冲区已满,这意味着等待,直到一些接收器中检索到值。接收器被阻塞,直到有数据接收。

##并发 (示例) 最后我们用一个例子来说明如何散落的内容拼起来。这是一个服务器通过管道来接受的Work请求的例子。每个请求都在一个单独的goroutine运行。 Work 结构本身包含了一个管道,用于返回一个结果。

package server

import "log"

// New creates a new server that accepts Work requests
// through the req channel.
func New() (req chan<- *Work) {
    wc := make(chan *Work)
    go serve(wc)
    return wc
}

type Work struct {
    Op    func(int, int) int
    A, B  int
    Reply chan int  // Server sends result on this channel.
}

func serve(wc <-chan *Work) {
    for w := range wc {
        go safelyDo(w)
    }
}

func safelyDo(w *Work) {
    // Regain control of panicking goroutine to avoid
    // killing the other executing goroutines.
    defer func() {
        if err := recover(); err != nil {
            log.Println("work failed:", err)
        }
    }()
    do(w)
}

func do(w *Work) {
    w.Reply <- w.Op(w.A, w.B)
} [server.go](http://www.nada.kth.se/~snilsson/go_for_java_programmers/src/server/server.go) 下面展示如何使用:

package server_test

import (
    server "."
    "fmt"
)

func main() {
    s := server.New()

    divideByZero := &server.Work{
        Op:    func(a, b int) int { return a / b },
        A:     100,
        B:     0,
        Reply: make(chan int),
    }
    s <- divideByZero

    add := &server.Work{
        Op:    func(a, b int) int { return a + b },
        A:     100,
        B:     200,
        Reply: make(chan int),
    }
    s <- add

    fmt.Println(<-add.Reply)
    // Output: 300
} [example_test.go](http://www.nada.kth.se/~snilsson/go_for_java_programmers/src/server/example_test.go) 并发编程是一个大主题,Java和Go的方法是完全不同的。要想充分体验到并发编程的乐趣,看这篇[Share Memory by Communicating(《通过沟通共享内存》)](http://golang.org/doc/codewalk/sharemem/)

Stefan Nilsson

该文基于相似的文章 《面向C++的GO编程》

参考: http://www.nada.kth.se/~snilsson/goforjava_programmers


Flex 4.6 自定义Datagrid添加checkbox\图片等功能

2012-03-28 Flex

flex 4.6 中的 spark 的Datagrid相比于之前的 mx 有很大不同

实现自定义<s:itemRenderer>详见代码~

<s:DataGrid id="dg" left="14" right="10" top="35" bottom="9" dataProvider="{datagrid_data}">
<s:columns>
<s:ArrayList>
<s:GridColumn headerText="程序名称"
dataField="name">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer>
<s:HGroup verticalAlign="middle">
<s:CheckBox id="cbx"/>
<s:BitmapImage width="24" height="24" source="{data.pic}"/>
<s:Label text="{data.name}"/>
</s:HGroup>
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
<s:GridColumn dataField="date" headerText="更新时间"/>
<s:GridColumn dataField="version" headerText="版本号"/>
<s:GridColumn dataField="moduleUrl" headerText="moduleUrl"/>
<s:GridColumn />
</s:ArrayList>
</s:columns>
</s:DataGrid>

flex4 ColumnChart外包裹NavigatorContent进行TabNavigator分页出错,柱子移位

2012-03-28 Flex

之前单页面的ColumnChart显示图标正常。 后来用TabNavigator进行分2页,每个页面用NavigatorContent, 在NavigatorContent中 再添加ColumnChart 出现了柱子移位的现象。

在ColumnChart 外包裹一层BorderContainer ,问题解决。~

<mx:TabNavigator id="tabnavigator1" width="100%" height="100%" >
<s:NavigatorContent id="nc_Id_1" label="调峰报告"
icon="@Embed('assets/icon/list/48.png')" width="100%" height="100%">
<ElectroLoadShifting:Usefuldays width="100%" height="100%" id="usefuldays_id"/>
</s:NavigatorContent>

<s:NavigatorContent id="nc_Id_2" label="调峰执行"
icon="@Embed('assets/icon/list/48.png')" width="100%" height="100%" >

<s:HGroup width="100%" height="100%" paddingLeft="1" paddingRight="10"
verticalAlign="middle" includeIn="loadingState">
<s:BorderContainer width="100%" height="100%" borderVisible="false" >
<s:HGroup width="100%" height="100%" >
<s:Label id="unit_id" width="18" height="100%"
text="{'用电量︵'+_model.loadingShitServerModel.unit+'︶'}"
verticalAlign="middle"/>
<s:VGroup width="100%" height="100%">
<s:Label text="近30天用电量"/>
<mx:ColumnChart id="column" height="100%" color="0x323232" width="100%"
showDataTips="true" dataProvider="{_model.loadingShitServerModel.datas}"
dataTipRenderer="common.skin.ColumnChart_DatatipSkin" creationComplete="init()"
>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="time"/>
</mx:horizontalAxis>

<mx:series>
<mx:ColumnSeries xField="time" yField="data" displayName="日用电量" id="columSeries_id" />
</mx:series>
</mx:ColumnChart>
</s:VGroup>

</s:HGroup>
</s:BorderContainer>

</s:HGroup>

<s:HGroup width="100%" height="100%" includeIn="coarseTurningState">
<ElectroLoadShifting:CoarseTurning id="coarseTurning_id" width="100%" height="100%"/>
</s:HGroup>
<s:HGroup width="100%" height="100%" includeIn="fineTurningState">
<ElectroLoadShifting:FineTurning id="fineTurning_id" width="100%" height="100%"/>
</s:HGroup>
<s:HGroup width="100%" height="100%" includeIn="powerSchemeState">
<ElectroLoadShifting:PowerScheme id="powerScheme_id" width="100%" height="100%"/>
</s:HGroup>

</s:NavigatorContent>

</mx:TabNavigator>

Q.yuhen推介的一些书籍

2012-01-28 Uncategorized

Q.yuhen:比较喜欢的一些图书,推荐给大家。

Linux 管理:

《Linux 系统管理技术手册》 案头必备的工具书。

《鸟哥的 Linux 私房菜》不错的入门书。

《Linux 101 Hacks》常用命令手册

《UNIX Shell Scripting》写脚本的参考书

《The Linux Command Line》更详细的命令手册

Linux 编程:

《Linux 系统编程》对常用 API 讲述最详细的一本书

《UNIX 环境高级编程》经典

《The Linux Programming Interface》与上本书配套

《程序员的自我修养》别被名字误导,极好的一本深度基础书。

《深入理解 Linux 内核》可以翻翻,对提升细节理解有好处。

《UNIX 网络编程》经典

《TCP/IP 高级编程》好书

C/C++:

《C 程序设计语言》入门书

《Lnux C 编程一站式学习》Linux 下开发的入门书

《C 语言核心技术》参考手册

《彻底搞定 C 指针》最好的指针入门书

《C++ 编程思想》经典

《高质量程序设计指南——C/C++语言》经典

《C 专家编程》

《C 和指针》

《C 陷阱与缺陷》

Golang:

《Learing Go》简单

《The Go Programming Language》比较详细

《The way to Go》提升

Javascript:

《Javascript, A Beginner’s Guide》

《Object-Oriented Javascript》

Python:

《Python Pocket Reference》适合经常翻翻

《Expert Python Programming》某些地方很有启发

其他:

《深入理解计算机系统》经典,必读

《计算机组成与设计》可以翻翻

《汇编语言》王爽 最好的汇编入门书

《数据结构》C 语言版 经典

《Java 数据结构和算法》更易阅读

《Debug Hacks 中文版》GDB 入门书

《设计模式——可复用面向对象软件的基础》经典

《MongoDB, The Definitive Guide》


Flex4 发布后访问,初始化极其缓慢的问题 解决方案

2011-07-14 Flex

  • Flex项目初始化太慢!Flex4为了加快加载速度使用了RSL,即把可以共享的框架、类库单独生成文件,并在请求时缓存到 Flash cache中,这样只要是同域的Flex项目就都可以使用而不必重新加载从而加快了加载时间。而问题也恰恰处在这个默认设置上,这些共享文件的优先位置是 从Adobe的服务端上下载,正是这个请求下载过程造成了加载奇慢。解决的办法就是将这些文件的位置优先指向自己的服务器(本地),Flash builder的Release 发布也可以生成这些文件,只要将这些.swz文件上传至服务器即可。

  • 如何设置RSL路径。网上找了半天,大多数是flex-config.xml,但这个是Flex3的,Flex4 默认是不使用这个文件了。在Adobe的帮助文档上找到了Customize the deployment location of the framework RSLs(http://help.adobe.com/en_US/flex/using/WS2db454920 e96a9e51e63e3d11c0bf69084-7add.html)设置方法如图,打开项目–属性–flex构建路径–库路径标签,点开 Flex4.1 选择framework.swc的链接类型–编辑–弹出库路径选项框。 可以看到默认的adobe的server路径在第一个,第二个是本地路径(要求与swf在同目录),将第二个调到第一位置(图中已调整)。当然也可以自定义路径,可以是相对的或绝对地址。点击确定保存设置。 这样依次设置 framework_4.6.0.23201.swz textLayout_2.0.0.232.swz 等等

  • 最后点击项目–导出发行版,在bin-releas下可以看到生成的.swz文件,第一次要把所有的文件上传到网站,以后只要是同域的其他Flex项目指定好RSL路径,就不必再上传.swz文件了,这样大大减小了swf文件的大小,加快了加载速度。

到此解决了开始的问题,同时使得RSL的优点也得到体现。

查考: http://forums.adobe.com/message/2428795#2428795 http://blog.163.com/vituk93@126/blog/static/170958034201282222046364/


Tomcat设置,输入IP地址 ,直接访问项目主页

2011-05-24 Tomcat

1.cmd 命令 看下 80 端口是否被占用

netstat -ano

2.没有被占用的话,将tomcat的端口设成80

配置文件的路径为\pache Software Foundation\Tomcat 6.0\conf\server.xml

<Connector port="80" protocol="HTTP/1.1" 
connectionTimeout="20000" 
redirectPort="8443" URIEncoding="UTF-8"/>

3.修改tomcat配置,默认访问指定项目

在<host />里面添加如下:

<Context path="" docBase="D:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\abc" />

docBase 是你的项目路径

这样 ,直接输入IP地址,就会映射到你的项目的index.html

 


Flex 4.6 XML搜索、匹配示例

2011-05-20 Flex

效果见图

初始化界面

输入“设置”,进行搜索、匹配后界面

下面是代码 <?xml version=”1.0” encoding=”utf-8”?> <![CDATA[ import mx.events.FlexEvent; import mx.utils.StringUtil; import spark.events.TextOperationEvent;

		public var rawList:XML = 
			<apps name="应用程序" >
			  <item name="关于"
			  		icon="plugins/about_002/assets/icons/about_48.png" 
			  		iconSmall="plugins/about_002/assets/icons/about_24.png" 
			  		moduleUrl="plugins/about_002/Ahout_002.swf"
			  		version="1.0"  date="2013-5-13"  author="way" type="plugin"
			  		description="关于能源管理中心的一个说明" />

			 <item name="程序管理" 
			  		icon="plugins/appManager_001/assets/icons/apps_48.png" 
			  		iconSmall="plugins/appManager_001/assets/icons/apps_24.png"
			  		moduleUrl="plugins/appManager_001/AppManager_001.swf"
			  		version="1.0"  date="2013-3-5"  author="way" type="plugin"  resizable="false"
			  		description="对系统应用,及用户自定义应用进行管理"
			  		shortCutCreated="true"/>

			  <item name="导航设置" 
			  		icon="plugins/navigatorSetting_001/assets/icons/gears_48.png" 
			  		iconSmall="plugins/navigatorSetting_001/assets/icons/gears_24.png" 
			  		moduleUrl="plugins/navigatorSetting_001/NavigatorSetting_001.swf"
			  		version="1.0"  date="2013-3-13" author="way" type="plugin" resizable="false"
					description="对导航进行设置"/>
			  <item name="主题设置" 
			  		icon="plugins/themeSetting_001/assets/icons/icon_48.png" 
			  		iconSmall="plugins/themeSetting_001/assets/icons/icon_24.png" 
			  		moduleUrl="plugins/themeSetting_001/ThemeSetting_001.swf"
			  		version="1.0"  date="2013-3-5" author="way" type="plugin" resizable="false"
			  		description="对系统的主题、样式进行设置"/>
		    </apps>
			;     

		[Bindable]
		public var rawListShow:XML = null;  //搜索过滤后的数据

		protected function init(event:FlexEvent):void
		{
			getData();
		}

		protected function textinput1_changeHandler(event:TextOperationEvent):void
		{
			getData();
		}

		//初始化数据
		private function getData():void{
			if(StringUtil.trim(textInput.text) == ""){
				rawListShow = rawList ;

			}else{
				createNewXml(textInput.text,rawList);
			}

			/* 打开或关闭指定项目下的所有树项目。如果设置 dataProvider 之后立即调用 expandChildrenOf(),
			则您可能看不到正确的行为。您应该等待对组件进行验证或调用 validateNow() 方法 */
			tree1.validateNow();

			expandtree();
		}

		//搜索过滤后,生产新的xml
		private function createNewXml(searchString:String, xml:XML):void{
			rawListShow =<apps  name="应用程序" />;

			for(var i:int = 0; i<xml.children().length(); i++)
			{
				var itemXml:XML = xml.child("item")[i];
				if(isInStr(searchString,[email protected]())){   
					rawListShow.appendChild(itemXml);
				}
			}
		}

		//判断search_str是否在str内 
		public function isInStr(search_str:String , str:String):Boolean{    
			var num:int= str.indexOf(search_str);
			if(num>-1){
				return true;
			}else{
				return false;
			}
		}

		//展开树
		private function expandtree():void {
			for each(var item:XML in this.tree1.dataProvider)
			this.tree1.expandChildrenOf(item,true);
		}

	]]>
</fx:Script>
<fx:Declarations>
	<!-- 该例子由waylau.com提供-->
</fx:Declarations>
<s:TextInput prompt="请输入要搜索的字段"  x="10" y="10" 
			 change="textinput1_changeHandler(event)" id="textInput"/>
<mx:Tree id="tree1" dataProvider="{rawListShow}" 
		 labelField="@name" width="200" height="300" x="10" y="40">
</mx:Tree>

<s:Label text="更多例子 请关注  waylau.com" x="10" y="360"/>
</s:Application>

简单实现浏览国外著名网站的方法,不用梯子,修改本机的 hosts

2011-04-28 Web

修改本机的 hosts 文件

一般的

hosts文件在不同操作系统(甚至不同Windows版本)的位置都不大一样: Windows NT/2000/XP/Vista/7/8(即微软NT系列操作系统):默认位置为%SystemRoot%\system32\drivers\etc\,但也可以改变。动态目录由注册表键\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DataBasePath决定。 Windows 95/98/Me:%WinDir%
Linux及其他类Unix操作系统:/etc Mac OS 9及更早的系统:System Folder: Preferences或System folder(文件格式可能与Windows和Linux所对应的文件不同) Mac OS X:/private/etc(使用BSD风格的hosts文件) OS/2及eComStation:”bootdrive”:\mptn\etc
Android:/system/etc/hosts Symbian第1/2版手机:C:\system\data\hosts Symbian第3版手机:C:\private\10000882\hosts,只能使用兼容AllFiles的文件浏览器访问,大部分都不行[1]。 iOS(iPhone):/etc iOS(iPad):/private/etc webOS:/etc

文件中添加要访问的IP 和 域名即可

127.0.0.1 localhost
127.0.0.1 activate.adobe.com
74.125.224.231 drive.google.com
203.208.46.206 m.youtube.com
203.208.46.206 s.ytimg.com
203.208.46.206 www.youtube.com

hosts文件也可以用于其它情况,例如可以将已知的广告服务器重定向到无广告的机器(通常是本地的IP地址:127.0.0.1)上来过滤广告。同时也可以通过不下载网络广告,从而减少带宽。使用hosts文件还可以减少对DNS服务器的访问来加快访问速度并减少带宽消耗。 hosts文件的另一个重要用途就是用于拦截一些恶意网站的请求,从而防止访问欺诈网站或感染一些病毒或恶意软件。但同时,这个文件也可能被病毒或恶意软件所利用来阻止用户更新杀毒软件或访问特定网站。

文章参考:http://zh.wikipedia.org/wiki/Hosts%E6%96%87%E4%BB%B6

更多参数看考:http://code.google.com/p/smarthosts/

http://code.google.com/p/huhamhire-hosts/



Flex addChild与addElement的区别

2011-01-01 Flex

  • addChild()接受的是一个DisplayObject对象,addElement()接受的是一个IVisualElement对象,IVisualElement是在Flex 4组件中开始应用的,所以Flex 3当中的组件没有实现IVisualElement接口,再所以Flex 3当中的容器用的是addChild()。
  • 而Flex 4中的spark组件已经实现了IVisualElement接口,所以可以用addElement(),在Flex 4中使用Flex 3的组件和其它没有实现IVisualElement接口的组件时,可以使用addElement(UIComponent(flex_3_comp)),就相当于用UIComponent来做一下包装。
  • 在Flex 4容器中,其实内建了一个Group类型的contentGroup用来存放容器中的元素,而正是Group类定义了addElement(),所以Flex 4容器不用addChild(),而是用addElement()
  • 如果是spark(如s:Group)容器,用addElement。如果是hola(如mx:Hbox)容器,就用addChild。

参考:http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf62b90-7fe9.html


校园网信息网络安全问题以及对策综述

2010-05-31 Security

摘要: 21世纪,计算机网络技术飞速发展,网络改变了人们的生活方式、学习方式,也为学校信息化建设注入了新的生机活力。但同时由于网络的自身开放性、互联性和共享性的特点,也为校园网的安全带来的威胁和挑战。校园网不可避免地受到病毒、黑客、恶意程序和其它的安全威胁和攻击,造成校园网数据丢失、系统被改、网络瘫痪等。本文分析了校园网的现状特点和存在的主要问题,提出了应对校园网威胁的安全策略。

关键词: 计算机网络;校园网;威胁;防范




Way Lau

Software Engineer and Full Stack Developer, now work and live in Shenzhen, China. Detail

Donate

See the list of Donors.