记录学习点滴
Jul 10
需求概述

鉴于公司需要开始研发桌面客户端产品,所以必须先对桌面客户端开发进行技术选型。此wiki将记录整个选型过程及结果。
流行的桌面开发软件

1. node-webkit

基于node.js和chromium的应用程序实时运行环境,可运行通过HTML(5)、CSS(3)、Javascript来编写的本地应用程序。 node.js和webkit的结合体,webkit提供DOM操作,node.js提供本地化操作;且将二者的context完全整合,可在HTML代 码中直接使用node.js的API。

支持的平台:Windows 32bit,Linux 32/64bit,Mac 32bit(OS X 10.7+)

参考文档

2. tideSdk

Tide SDK 是一个让你使用你的 Web 开发技能来创建漂亮而且独特桌面应用的开发工具包。支持跨平台开发。

参考资料

3. AppJS

AppJS 是一个令人振奋的 JavaScript 库,使我们能够使用 Web 技术快速开发桌面应用程序(HTML,CSS和JavaScript)。AppJS 使用 Node.js 做为后端支撑。

参考资料

PS:最后讨论决定,使用node-webkit构建我们的桌面客户端程序。

Node-Webkit的使用(概述)

1.下载及安装

下载地址:

https://github.com/rogerwang/node-webkit

下载完Mac版本后直接解压,得到node-webkit的app文件,不需要特殊安装。

为了方便以后处理,我把它移动到我的opt目录下,并设置命令别名



#从下载解压目录移动到opt下面

mv /Users/jason/Downloads/node-webkit-v0.6.1-osx-ia32 /opt/node-webkit

#拷贝一份app供后面打包使用

cp -R /opt/node-webkit/node-webkit.app /opt/node-webkit/create.app

#添加别名命令,当日可以直接加到命令文件中,以后直接使用nw就可以对应用进行运行调试

alias nw="/opt/node-webkit/node-webkit.app/Contents/MacOS/node-webkit"



参考资料

https://github.com/rogerwang/node-webkit/wiki/How-to-run-apps

2.第一个node-webkit应用的诞生

#在 opt下面建立一个nwapp目录存放后续的nw应用,创建一个测试目录

mkdir /opt/nwapp

mkdir /opt/nwapp/test

#创建包文件及主文件

touch /opt/nwapp/test/package.json

touch /opt/nwapp/test/main.html

文件内容如下:

package.json

{
"main":"main.html",
"name":"test"
}

main.html

< !DOCTYPE HTML>
< html lang="en-US">
< head>
< meta charset="UTF-8">
< title>Hello World< /title>
< /head>
< body>

< style type="text/css" >

    body {

        -webkit-user-select:none;

        -webkit-app-region:drag;

    }

< /style >

Hello World!
< /body>
< /html>

#使用nw命令调试

nw /opt/nwapp/test

调试结果如下:

  

3.打包成为app应用

3.1 MacOS下面

#进入应用所在目录打包文件

zip ../app.nw *

#将生成的app.nw文件放入到create.app对应目录下

cp ../app.nw /opt/node-webkit/create.app/Contents/Resources/

#修改create.app成应用的名字,打包完毕、、、是不是很神奇?

mv /opt/node-webkit/create.app /opt/node-webkit/test.app

这时候,test.app  就可以直接在mac下面点击打开了。。。

3.2 linux下面

3.3 Windows下面

NodeJS入门

1.Mac下面NodeJs的安装

直接访问 http://nodejs.org 找到下载页面下载,Mac版本的node安装文件,并安装即可。

新版的Node安装包里面包括了npm组件,不需要单独再安装

安装完成之后,直接在终端输入 node,如果显示一个 ">" 表示进入了node的REPL模式,说明安装成功了。

2.安装supervisor监视代码改动

由于node默认每次修改代码都需要重新启动Node,这是开发人员所不能接受的。

所以我们安装supervisor,来解决这个问题,它可以监视代码改动并自动重启Node

安装命令:

npm install -g supervisor

安装完毕之后用supervisor命令替换node命令即可

如:

supervisor xxx.js

3.第一个Node程序,hello node

文件:hello.js

内容:console.log('hello node');

运行:node hello.js, 如下图

4.node模块

4.1 模块概念

将独立的一些功能分装到一个文件里面,就形成了一个node模块,每个模块都需要通过exports和require对象来定义和引用。

4.2 模块只会单次加载,所以不论引用多少次,对象都没有变,如下例



4.3 我们可以覆盖module中的方法,如下图:

5.node中的包

概念:包就是将一个功能下的多个模块按规则集合在一个目录下,规则写在根目录下的package.json文件中

默认文件:首先寻找package.json中的main字段,没有则寻找根目录下的index.js文件或者index.node文件作为入口

package.json规范字段:

name,description,version,keywords(数组)等等

6.node包管理器npm

6.1 本地模式和全局模式

本地模式默认将包安装到当前目录的node_modules目录中,全局模式则安装到系统/usr/local/bin中并默认添加了环境变量,全局模式将无法通过require使用。

安装命令: npm [install/i] [package_name]

全局模式命令: npm [install/i] -g [package_name]

6.2 创建链接

可以使用 npm link [package_name] 将本地、全局模式相链接,类似与ln,不支持windows

PS:如果不了解ln,不推荐使用

6.3 发布包

npm init

7.node 调试

1.命令行调试 node debug xxx.js

常用命令:

run,执行单步调试

restart,重新执行

c, 继续执行直到下一个断点

n, 继续单步执行

s,单步执行并进入函数

o, 跳出单步执行

sb(xxx.js,N),在第N行设置断点,默认为当前行

cb(), 清除所有断点

list(5),显示当前执行处的前后5行代码

kill,中止当前脚本

2.使用node-inspector调试node.js
Node核心模块的熟悉

1.全局对象与全局变量

在Node中,全局变量名为global,所有寄存在其上的变量都是全局变量,如console,process。

模块中所有变量定义,都加上var,避免污染全局变量。

process常用成员方法

process.argv     //获取命令行参数数组

process.stdout  //标准输出流,使用process.stdout.write()

process.stdin    //标准输入流,默认暂停,使用前要手动恢复:process.stdin.resume()

process.nextTick(func) //在下次循环调用响应时调用func方法,替换掉传统的setTimeout(func,0)方式

console

console.log(),console.error(),console.trace() //输出当前调用栈

2.常用工具 util

util.inherits(cons,superCons)  //让cons继承superCons对象原型中定义的方法,不包括superCons自身定义的属性和方法

util.inspect(obj)  //将一个对象转化为一个字符串输出。NB啊!

其他如util.isArray(),util.isRegExp(),util.isDate(),util.isError等

3.事件驱动events

events.EventEmitter()

EventEmitter.on(event,func) //指定监听event,回调函数为func

EventEmitter.emit(event,arg1,[arg2]..) //触发event,并传入参数给回调函数

EventEmitter.once(event,func) //为event指定一个一次性的监听,回调函数为func,触发后自动解除监听

EventEmitter.removeListener(event,func) //为事件移除监听func

EventEmitter.removeAllListeners([event])   //为某个事件移除所有监听,不指定则移除所有监听

error事件,

如果一个对象会触发error事件,我们一般会为它设置一个error监听,以免影响整个程序。

使用,一般不会直接使用EventEmitter,而是在对象中继承它。

4.文件系统fs

所有文件操作都有同步和异步两个版本的函数,如readFile和readFileSync,同步函数回调函数第一个参数为err。

常用函数:

fs.readFile(file,[encode],[callback]) // 如果没有encode,则callback就是第二个参数,有err和data两个参数。

fs.open(path,flags,[mode],[callback]) //打开文件,flags 为读取方式,如r,w,r+,mode为创建文件时给的权限,callback有err,fd 2个参数

fs.close(fd,callback),

fs.writeFile(filename,data,[encode],[callback])

fs.unlink(path,[callback])

fs.mkdir(dir,mod,callback)

fs.rmdir(dir,callback)

fs.readdir(dir,callback(err,files))

fs.realpath(path,callback(err,realpath))

fs.rename(path1,path2)

fs.stat(file,callback(err,info)) //获取文件信息

5.HTTP服务器和客户端

5.1 http服务器对象http.server,继承自EventEmitter。

可监听的事件

request (请求到达时,提供req = http.ServerRequest、res = http.ServerResponse 两个参数)

connection (TCP建立链接时,提供参数socket = net.socket)

close (服务器关闭时触发事件,不是用户断开链接时)

代码示例:(request)

5.2 HTTP请求信息 http.ServerRequest

可监听的事件

data (请求数据到来时触发,提供参数chunk)

end (请求传输完成时触发,不再接受新数据)

close (请求结束时出发)

属性包括:complete(是否已完成)、method(请求方式)、url(原始请求路径)等

5.3 HTTP服务器返回给客户端的信息 http.ServerResponse

成员函数

writeHead(status code,[headers]),向请求的客户端发送响应头

write(data,[encoding]) 向请求的客户端发送响应内容

end([data],[encoding]) 结束响应

5.4 HTTP客户端

提供了两个函数向服务器端发送请求,请求参数通过write添加,callback只有一个res参数,两个函数都返回http.ClientRequest的实例。

http.request(options,callback)  多用于post,结束时需要end,

http.get(options,callback) 多用于get,结束时不需要end

http.ClientRequest提供的函数

write,end,abort -- 中止,setTimeOut(time,callback) -- 设置超时,setNoDelay,setSocketKeepAlive等

代码示例:

只需要在命令行下面使用 node xxx.js 就可以调试了。
NodeWeb开发

1.Express框架介绍及本地环境的搭建

express是一个方便的轻量级node web开发框架,支持ejs模版解析引擎,默认为jade。

安装及调试方式:

第一步:全局安装express,方便开发

npm install -g express

第二步:建立本地工程test

express test

cd test && npm install

第三步:安装ejs支持,可以通过express -h 查看最新命令

express -e

第四步:启动服务器

node app  //当然开发时也可以使用 supervisor app 进行代码修改监控

2.路由控制

2.1 静态文件目录设置

app.use(express.static(path.join(__dirname, 'public')));

2.2 路由规则指派

app.get('/',routes.index); //将所有访问路径为“/”的请求由routes.index控制

app.get('/user/:uname',routes.user); //将所有访问“/user/xxx”的请求路由到routes.user,在routes.user中,可以使用req.params.xxx得到对应的请求参数值

app.get(\/user\/([^\/]+)\/?,routes.user); //将所有访问"/user/a/b/c.."的请求路由到routes.user中,可以使用req.params[0],req.params[1]等得到对应的a,b的值

其他方法还有 app.post(),app.put(),app.delete(),app.connect(),app.options(),app.trace(),app.all()等请求绑定函数,app.all表示对所有方式有效。

其中我们可以使用app.all()来做一些请求的中间件,重复利用代码,代码如下:

3.模板引擎(ejs)

3.1ejs标签系统说明(真是够简单的)

<% code %> :js代码

<%= code  %> ,替换过HTML的模板内容

<%- code %> ,原始的模板内容

3.2 自定义布局(layout属性)

res.reader('user',{title:'hello world',layout:'hello'}) //指定layout属性为hello,渲染的时候将以hello.ejs为页面布局

3.3 片段视图(子模板,使用partial引入)

3.4 视图助手

静态app.apphelpers和动态app.dynamicHelpers,让视图中可以直接访问全局的对象

动态助手的每个属性必须是函数,并且会传入req和res两个参数。
Node进阶
HTML5学习之入门
HTML5API介绍

HTML5构建WEB程序

NODE-WEBKIT中NODE与HTML5的运用

Aug 31
1. for,foreach 一个数组
float f[]= new float[10];
for(int i=0;i<10;i++){
f[i] = i;
}

for(float x:f);
//将每个f元素赋值给每个x 相当与 php的foreach(f as x)

2.重载的区分
2.1方法的重载:一个类中包括多个同名的方法
2.2 不同参数类型来区分
2.3 不同类型参数顺序不同来区分

3.不要到处使用this,this只用在区分不同实例的情景下

4.构造器调用构造器
4.1说明:一个类可以有多个同名构造器,区分方式如方法的重载
4.2 demo
public class Demo{
     int d = 0;
     String s = ' here :';
     Demo(int t){
          d= t;
          this('d='+d); //构造器调用构造器
     }
     Demo(String ss){
         s += ss;
         System.out.println(s);
    }
}

4.3构造器只能在构造器中被调用

5.显示的初始化 {}

public class Spoon{
     static int i;
     static {
          i = 47;          
     }
     DemoClass a;
     DemoClass b;
     {
         a = new DemoClass(1);
         b = new DemoClass(2);
    }
    
}

6.数组的string化

Arrays.toString(f);


Aug 31
1.组合语法a.toString
b.toString
2.继承语法
extends (构造器调用,默认不带参数)

3.代理


Aug 31
前言,一切都是对象,
0.1 用引用操作对象,如遥控器遥控电视
0.2 用new创建对象


1. 每个对象都有一个接口  obj.xxx

2.每个对象都提供服务
xxx 肯定做了什么事

3.隐藏具体实现
xxx 用 private等进行权限控制

4.复用具体实现
obja 有方法xxx,objb 有方法 xxx.

5.继承
obja 是obj的一个子类

6.多态
obja.xxx和 objb.xxx是不一样的

7.单根继承
obja 和 objb 都是继承自obj

8. 容器(集合)

9.生命周期
对象创建-撤销

10.异常的处理

11.并发编程
Aug 31
#### 一.服务器端支持 ####

1. openoffice.org3.0 + jodconverter + swftools



原理:开启openoffice监听,利用jodconverter调用oo3的转换脚本将 office文件转换成pdf文件。

          再通过swftools将pdf文件转换为swf文件



前提:安装OpenOffice,安装OpenOffice SDK3.3,jodconverter及swftools,并开启openoffice监听

环境变量:

export PATH=$PATH:/usr/local/swftools/bin/




shell下命令:



第一步:开启openoffice监听 8100端口

export DISPLAY=localhost:2.0

Xvfb :2 -screen 0 800x600x24 2> /dev/null &

/usr/lib/libreoffice/program/soffice --accept="socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" --nologo --headless --nofirststartwizard --display :2 &



第二步:通过jodcconverter转换文档成pdf

java -jar /opt/jodconverter-2.2.2/lib/jodconverter-cli-2.2.2.jar /opt/lampp/htdocs/sociax/1.txt /opt/lampp/htdocs/sociax/text.pdf



第三步:将pdf转化为swf、txt文件

//转化为swf -- 展示用
pdf2swf -s languagedir=/usr/local/xpdf-chinese-simplified -T 9 -s poly2bitmap -s zoom=72 -s flashversion=9 "/opt/123.pdf" -o "/opt/test/1.swf"
pdf2swf -s languagedir=/usr/local/xpdf-chinese-simplified -T 9 -s poly2bitmap -s zoom=30 -p 1 -s flashversion=9 "/opt/123.pdf" -o "/opt/test/1.swf"



//转化为txt纯文本 -- sphinx搜索用

pdftotext -q "/opt/lampp/htdocs/sociax/1.pdf" "/opt/lampp/htdocs/sociax/1.txt"







#### 二. java程序 ####



说明:通过计划任务定时执行java程序,通过java程序执行文档转化命令,转化文档。

注:如果能实现java程序内部监听,不需要服务器端计划任务配置,则为更佳的方案。





java程序结构



1. sociax.java

方法:main()

实现://伪代码



     loadConfig ()                    // 载入配置 conf/sociax.xml

     startTransformListener ()   // 调用转化(监听)程序,文件名称 :src/SociaxTransAdmin.java





2. conf/sociax.xml

要求:

能配置sociax数据库信息,包括host,port,database,username,password, prefix (表前缀)

转化信息:limit 单次转化的文件个数上限, filedir:文件路径前缀

能配置转化命令:(由于不同服务器安装的环境可能有区别)

com_file2pdf:java -jar /opt/jodconverter-2.2.2/lib/jodconverter-cli-2.2.2.jar $fileoffice $filepdf

com_pdf2swf: pdf2swf -s languagedir=/usr/local/xpdf-chinese-simplified -T 9 -s poly2bitmap -s zoom=150 -s flashversion=9 "$filepdf" -o "$fileswf"

com_pdf2txt:pdftotext -q "$filepdf" "$filetxt"





mysql
127.0.0.1
3306
root
123456
sociax
sociax_



20
/usr/data



java -jar /opt/jodconverter-2.2.2/lib/jodconverter-cli-2.2.2.jar $fileoffice $filepdf
pdf2swf -s languagedir=/usr/local/xpdf-chinese-simplified -T 9 -s poly2bitmap -s zoom=150 -s flashversion=9 "$filepdf" -o "$fileswf"
pdftotext -q "$filepdf" "$filetxt"



实现可参考:pdf2swf/conf/sociax.xml



3.sociaxTransAdmin.java

方法:startTransformListener()



参数:无

实现://伪代码



    initData();           //初始化数据将需要转化的内容导入到转换缓冲表

    trans_list =  getData();           //获取需要转化的数据 ,最多limit个,并保存到转换队列 变量 trans_list 中

    doTrans(trans_list);           //执行转化





方法:initData();

参数:无

实现:需要执行下面的sql:注意将里面的sociax_替换为配置的表前缀

String sql = "insert into  `sociax_document_cache` (aid,status,cTime)

select attach_id,0,ctime from sociax_doc where attach_id > ( select IFNULL(max(aid),0) from `sociax_document_cache` ) ";



参考:CrawlingFile.java 里面的 insertNoneTransformDoc函数



方法:getData();

参数: 自己定义

实现:需要执行下面的SQL,并返回结果,其中config.limi为配置的单次最多转化数

String sql="select doc.id,doc.aid,CONCAT(attach.save_path,'',attach.save_name) as outputFile from sociax_document_cache as doc left join sociax_attach as attach on  attach.attach_id = doc.aid where doc.status='0' limit 0,"+config.limit;





方法:  doTrans(trans_list);

参数:无

实现:伪代码

if( empty(trans_list) ){ return false;} //如果转化队列为空,则不执行转化操作

start();                                          //开始转化服务 -- 可能需要开启一些服务之类的,待调试

trans_ids = array();                        //转换的文件的id集合  

//开始对转换队列进行转化操作

for(i=0; i
     transfile(file);                           //单个文件的转化操作          

     ids []

}

updateDataBase(trans_ids);           //通过trans_ids集合将缓存表里面的status更新为1

stop();                                          //停止转化服务 -- 可能需要关闭一些服务之类的,待调试





方法:transfile(file)

参数:file,要转化的源文件

实现:伪代码

filepdf = file+'.pdf'   //新的pdf文件地址



if(file_exsit(filepdf)){ //判断新的pdf文件是否存在,存在则不继续下面操作 -- 不知道java里面怎么实现,交给你研究

     return false;

}



//判断是否为pdf文件,如果不是则执行转化命令,将文件转化成pdf,否则直接复制一份文件到pdf

if( !ispdf(file) ){

     do_commond = com_file2pdf; //转化成pdf的命令处理,注意源文件和目标文件

     xx.runcommend(do_commond);

}else{

     xx.runcommend('cp '+file+' '+filepdf);     //直接拷贝

}



//由于转化pdf需要一定时间,在转化成swf前要判断是否已经转化完了

//判断上一个执行操作是否结束 -- 不知道怎么实现的 看小鹏的ServiceAdmin.java: 里面有个isDone

if(xx.isDone()){

     do_commond =com_pdf2swf

     //将文件转化称swf

      xx.runcommend(do_commond);

     //将文件转化称txt 可以和上个命令一起执行,不需要判断是否已经执行完了

     do_commond =com_pdf2swf

     xx.runcommend(do_commond);

}





方法:updateDataBase(ids);

参数:ids,本次转化的文档id集合

实现:执行下面的sql,后面的in ids 需要java处理好

String sql = " update sociax_document_cache set status = 1 where  id in (''+ids+")";







#### 3.数据库修改 ####

新加一张文档转化cache表

CREATE TABLE IF NOT EXISTS `sociax_document_cache` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `aid` int(11) NOT NULL,

  `status` tinyint(2) NOT NULL,

  `cTime` int(11) NOT NULL,

  PRIMARY KEY (`id`)

) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;






#### 4. flexpaper显示swf部分 ####

这部分比较简单,后续补充






分页: 1/16 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]