IE 回车 提交表单问题

现在当我写一个form时,总是提心吊胆的,因为最近我几次遇到回车导致表单提交的情况,当然,这任然是在“神奇的IE”里面出现的奇迹。

这里所说的问题都是说在文本框里回车导致的,你在别的地方回车当然没这个问题。

网上有人总结了:

http://www.cnblogs.com/cxd4321/archive/2012/05/07/2486926.html

 

我们有时候希望回车键敲在文本框(input element)里来提交表单(form),但有时候又不希望如此。比如搜索行为,希望输入完关键词之后直接按回车键立即提交表单,而有些复杂表单,可能要避免回车键误操作在未完成表单填写的时候就触发了表单提交。

要控制这些行为,不需要借助JS,浏览器已经帮我们做了这些处理,这里总结几条规则:

1、如果表单里有一个type=”submit”的按钮,回车键生效。

2、如果表单里只有一个type=”text”的input,不管按钮是什么type,回车键生效。

3、如果按钮不是用input,而是用button,并且没有加type,IE下默认为type=button,FX默认为type=submit。

4、其他表单元素如textarea、select不影响,radio checkbox不影响触发规则,但本身在FX下会响应回车键,在IE下不响应。

5、type=”image”的input,效果等同于type=”submit”,不知道为什么会设计这样一种type,不推荐使用,应该用CSS添加背景图合适些。

实际应用的时候,要让表单响应回车键很容易,保证表单里有个type=”submit”的按钮就行。而当只有一个文本框又不希望响应回车键怎么办呢?我的方法有点别扭,就是再写一个无意义的文本框,隐藏起来。根据第3条规则,我们在用button的时候,尽量显式声明type以使浏览器表现一致。

我再补充type=”image”的BT情况,当用户会车时,竟然会触发这种标签的onclick事件---这就是奇迹,它就在那里!

 

然后再联系一下IE form提交的另外的问题http://blog.ureshika.com/archives/356.html , 这就是我为什么提心吊胆的原因了。

Continue reading IE 回车 提交表单问题

oracle11g XE 使用经历

我这次使用oracle 11g XE(express edition)算是浅尝辄止,我的机器几年前装过8,9i都不是很卡,几年过去,都到11g了,安装到很顺利,但是一开服务,我的机子就做不了事了,开个网页都卡的不行。

还试用了sql developer 3,不需要oracle客户端(TNS连接方式), sql编辑按空格有提示。

导入客户的sql脚本,结果n多表空间要建,真是麻烦。

用惯了mysql现在不习惯oracle这个笨家伙了,我的mysql服务一直开机启动,根本没什么影响。

 

另外在oracle官网上下载都需要注册oracle用户,且速度奇慢。

Continue reading oracle11g XE 使用经历

askterisk笔记【二】

第二十章 AMI

Asterisk Manager Interface主要提供AST系统监控以及管理功能,它可以要求AST做一些事情,例如发起一个新呼叫。

需要的配置:

manager.conf

;
; 打开AMI并本地访问
[general]
enabled = yes
webenabled = yes
bindaddr = 127.0.0.1
;
; 创建用户hello,密码world
;
[hello]
secret=world

上面的配置打开了http访问,这个需要配置http.conf(注意这个不是apache的httpd.conf)但是我安装的ASteriskNow并没有这个http.conf配置文件,也没打开http访问,常见的还是使用tcp访问,默认端口是5038。

如果没发现这个文件http.conf,可以自己加一个:

[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
prefix=gui                          ;这个前缀用于http请求的url前缀
enablestatic=yes

这样的话请求AMI应该是:

http://localhost:8088/gui/rawman?action=login&username=hello&secret=world

然后重新加载:CLI>core reload

如果登陆不成功,还要看manager.conf中deny设置是否禁止了你的ip访问。

协议:

主要有两种协议:

Manager events 只从AST到AMI客户端的单项事件

Manager actions AMI客户端请求AMI会得到返回Action Response。

对于http连接,事件需要通过poll来获取。

下面是开源AMI客户端库。

Adhearsion Ruby http://adhearsion.com/
StarPy Python http://starpy.sourceforge.net/
Asterisk-Java Java http://asterisk-java.org/

介绍几个有用的AMI应用:

Asterisk GUI这个包含在AsteriskNow中 ,参见http://www.asterisk.org/asterisknow/developers/gui-guide

 

第二十一章 AGI

内置的dialplan写法可能有很多不便之处(如果你熟知一门编程语言的话),使用AGI则可以使用其他编程语言来控制呼叫流程,但是这么做还是离不开native dialplan的参与。

例如

exten => 500,1,AGI(hello-world.sh)

这里就调用了shell脚本的AGI

打开AGI调试:

*CLI> agi set debug on

AGI变种

Process-Based AGI:

最简单的AGI,调用方式AGI(command[,arg1[,arg2[,...]]]) command可以使绝对路径,相对路径,arg1…是AGI需要传入的参数。

执行AGI时,与AST交互的方式是通过stdin 和 stdout来进行的。

有点:简单

缺点:太简单,高并发时建议使用FastAGI

EAGI (Enhanced AGI)

相对于AGI,除了stdin和stdout外还可以获得单向只读语音流(app_jack提供获得AST之外音频流的功能)。

*CLI> core show application EAGI

优点:简单

缺点:性能消耗比Process-Based AGI高

DeadAGI

这个已被废弃,不要使用。

FastAGI—AGI over TCP

使用tcp连接,不再是每个call一个进程,提高效率。

exten => 1234,1,AGI(agi://192.168.1.199:4573,arg1,arg2,arg3)

FASTAGI支持srvrecord

exten => 1234,1,AGI(hagi://shifteight.org)

优点:效率较好

缺点:实现FASTAGI Server比较复杂

Async AGI—AMI-Controlled AGI

异步AGI,可以使AMI调用AGI。

exten => 1234,1,AGI(async:agi)

这种方式的流程是,当执行上面一句时,会等待,然后,在AMI客户端中向·这个通道发命令,以这样的方式来执行。

对于要执行AGI的影虎需要在manager.conf中指明权限

[hello]
secret = world
read = agi    ;有读权限
write = agi  ;有写权限

优点:AMI可使用AGI

缺点:最复杂的一种用法

会话过程

调用AGI或EAGI后,会话建立,自定义参数(如agi_arg_0)和固有参数(如agi_request)会传入:

对于Async AGI,开始时AMI会发送事件Manage Events,例如:

Event: AsyncAGI
Privilege: agi,all
SubEvent: Start
Channel: SIP/0000FFFF0001-00000000
Env: agi_request%3A%20async%0Aagi_channel%3A%20SIP%2F0000FFFF0001-00000000%0A \
agi_language%3A%20en%0Aagi_type%3A%20SIP%0Aagi_uniqueid%3A%201285219743.0%0A \
agi_version%3A%201.8.0-beta5%0Aagi_callerid%3A%2012565551111%0A \
agi_calleridname%3A%20Julie%20Bryant%0Aagi_callingpres%3A%200%0A \
agi_callingani2%3A%200%0Aagi_callington%3A%200%0Aagi_callingtns%3A%200%0A \
agi_dnid%3A%20111%0Aagi_rdnis%3A%20unknown%0Aagi_context%3A%20LocalSets%0A \
agi_extension%3A%20111%0Aagi_priority%3A%201%0Aagi_enhanced%3A%200.0%0A \
agi_accountcode%3A%20%0Aagi_threadid%3A%20-1339524208%0A%0A

一旦会话开始,AGI就可以发送命令和获得回应,命令的执行是序列化的,一个执行完毕才会执行下一个。

AGI会话的终止

各种AGI的行为不一样:

Process-based AGI/FastAGI:

会话挂断会通知AGI程序来做后续处理。(1.4之前是直接中断,不会通知)

Process-based AGI 会发SIGHUP 信号

FASTAGI会发HANGUP信号。

可以通过这样来禁止发送SIGHUP /HANGUP信号:

;
; Don't send SIGHUP to an AGI process
; or the "HANGUP" string to a FastAGI server.
;
exten => 500,1,Set(AGISIGHUP=no)
same => n,AGI(my-agi-application)

如果禁用,则相当于DeadAGI模式,会话其实结束了,但仍可以执行。不过只能执行不需要交互的命令,具体看每个命令的文档说明。

对于Async AGI,如果会话中断,会发中断提示,如果想要主动中断会话,AMI客户端需要发送ASYNCAGI BREAK命令。

AGI各种开发语言库:

Adhearsion Ruby http://adhearsion.com/
StarPy Python http://starpy.sourceforge.net/
Asterisk-Java Java http://asterisk-java.org/
Asterisk-perl Perl http://asterisk.gnuinter.net/
PHPAGI PHP  http://phpagi.sourceforge.net/

第二十五章 web 接口

这一章介绍了有名的相关项目:

坐席管理

http://www.asternic.org/ Flash Operator Panel 免费

http://www.fop2.com/  Flash Operator Panel2 15个以上收费

http://www.cdr-stats.org/ Call Detail Records 分析统计工具

http://www.asterisk2billing.org/ 计费系统 A2Billi ng

 

第十八章 外部服务

使用XMPP

需要res_jabber模块,默认是没有安装的,如果要支持gtalk的话,需要chan_gtalk,chan_jingle(这两个依赖res_jabber)

centos上需要iksemel:

yum install iksemel-devel openssl-devel

现在假设res_jabber安装好了,需要配置 jabber.conf

[general]
debug=no
autoprune=no
autoregister=yes
auth_policy=accept
[asterisk]
type=client
serverhost=talk.google.com                   ;这里连到了gtalk
username=asterisk@shifteight.org    ;xmpp用户名
secret=<super_secret_password>     ;xmpp密码
port=5222
usetls=yes
usesasl=yes
status=available
statusmessage="Ohai from Asterisk"

 

dialplan:

exten => 106,1,Verbose(2,Example using the Local channel) ;一开始就呼叫dialplan
same => n,Dial(Local/jabber@${CONTEXT}/n&Local/dial@${CONTEXT}/n)
exten => jabber,1,Verbose(2,Send an XMPP message and expect a response) ;接到呼叫发送xmpp消息
; *** This line should not have any line breaks
same => n,JabberSend(asterisk,leif.madsen@gmail.com,Incoming call from
${CALLERID(all)}. Press 2 to send to voicemail.) ;消息不能换行
same => n,Set(JabberResponse=${JABBER_RECEIVE(asterisk,leif@shifteight.org,6)})
same => n,GotoIf($["${JabberResponse}" = "2"]?voicemail,1)
same => n,Hangup()
exten => dial,1,Verbose(2,Calling our desk)
same => n,Dial(SIP/0000FFFF0002,15)
same => n,Goto(voicemail,1)
exten => voicemail,1,Verbose(2,VoiceMail)
same => n,Answer()
; *** This line should not have any line breaks
same => n,Set(VoiceMailStatus=${IF($[${ISNULL(${DIALSTATUS})}
| "${DIALSTATUS}" = "BUSY"]?b:u)})
same => n,Playback(silence/1)
same => n,VoiceMail(100@lmentinc,${VoiceMailStatus})
same => n,Hangup()

这个例子是通过发送xmpp消息来让xmpp用户来选择。

与skype整合

可以通过skype发、接消息,呼叫好友

LDAP整合

 

TextToSpeech

Festival 和 Cepstral 引擎

 

暂看到这里……

Continue reading askterisk笔记【二】

askterisk笔记【一】

先看看这些:
相关技术书籍
http://www.asteriskcn.com/index.php?q=forum/14

Asterisk,电话未来之路 这本书翻译得有些生硬,有时看得莫名其妙。

建议先看其第7,8章。 理解电话技术和voip协议。

第七章 理解电话技术

引起振铃音的交流电压和给电话机供电的直流电压.

PS:

电话线里的电压是变化的,既有直流也有交流。
电话在待机的时候,电话线里的电压是负48伏直流,摘机后的电压是正12伏直流,负载一路5伏交流音频信号,合17伏峰值。
振铃时的电压是负48伏直流负载一路75伏交流振铃脉冲,合110伏峰值。

电话响铃时还是有点危险的(人体的安全电压是36伏)。

数字电话,目前我GUO 从家庭到中心局似乎还是模拟技术。

奈奎斯特定理表述为:

“在对信号采样时,采样频率必须高于输入信号带宽的两倍以上才能根据采样信息很好的重构原始信号。”

压扩是一种提高采样动态范围而不丢失重要精度的方法。它工作的原理是量化比较高的振幅时用更大的粒度,量化比较低振幅用比较小的粒度。换句话说,如果你对着电话喊叫,对你声音的采样不像正常讲话那样清晰。喊叫对你的血压不利,所以最好避免。


通常使用两种压扩方法:在北美用μ律,世界的其他地方用A 律。这两种方法的工作原理相同,但是相互不兼容。

在数字音频系统中(正如现代PSTN),如果送到模拟-数字转换器的频率超过采样频率的二分之一就会发生混叠现象(Aliasing)

PSTN 中,有许多不同容量的电路来满足网络的各种需求。局端和用户之间,通常有一条或多条模拟线路,或者通过数字电路传输的几十个通道。在PSTN 的交换局之间(或者大客户),通常使用光纤。

电话呼叫数字化的标准方法是以8 比特每秒采样8000 次,所以我们知道PCM(脉冲编码调制) 编码的电话电路需要的带宽是64,000 bps。这种64-kbps 的通道被称为。DS-0是数字化电信电路的基本模块。

一个T-1 由复用在一起,形成一个1.544-Mbps 的比特流[*]。这个比特流的正式定义是DS-1。

欧洲是E1,一条E1作为32个64K来用,但是时隙0和时隙15是传输控制信令用,所以一条E1可以传30路话音。

这似乎是说,欧洲一条普通电话线可以接30个分机 ?

我朝似乎也是E1?

Asterisk开发:http://blog.csdn.net/lin_bei/article/details/2536569

目前看似乎Asterisk和freepbx都可以用php开发。

 

api文档:

http://www.asterisk.org/astdocs/api/index.html

最新版本AGI AMI 文档:

https://wiki.asterisk.org/wiki/display/AST/Asterisk+Command+Reference

Asterisk权威文档(第3版).pdf http://ishare.iask.sina.com.cn/f/24400557.html

 

以下是权威文档笔记:

Asterisk简称为AST

Zapata是连接pstn与计算机的项目,现在发展为Digium Asterisk Hardware Device Interface (DAHDI),可以说它是AST的pstn 引擎。

第二章 Asterisk结构

Asterisk Dialplan 处理各种channel的方式是一致的。

AST基于Modules, 分为:

• Applications

extensions.conf里面的dialplan将会使用的程序


• Bridging modules

1.8新特性,主要被app_confbridge使用


• Call detail recording (CDR) modules

通话记录,书中说没什么用,推荐的记录方式应该使用channel event logging


• Channel event logging (CEL) modules

事件记录


• Channel drivers

channel驱动,例如sip驱动


• Codec translators

不同语音流编码之间的转换,例如pstn到sip


• Format interpreters

语音文件格式转换,如wav到目标channel


• Dialplan functions

dialplan app用到的函数


• PBX modules

外围的pbx配置,加强机制。


• Resource modules

ast与外界资源,如odbc连接


• Addons modules

社区贡献的加强模块,默认是没安装的。


• Test modules

开发者使用的测试模块

文件结构:

配置在/etc/asterisk/中

模块文件夹默认在/usr/lib/asterisk/modules,注意,当更新asterisk使用menuselect选项的话,不会自动删除无用的模块,需要手动删除或使用make uninstall

资源文件夹为/var/lib/asterisk ,包含moh,系统提示,AGI脚本等

临时文件 /var/spool/asterisk 存储录音,text到语音

日志文件夹 /var/log/asterisk

dialplan 有三种写法:

/etc/asterisk/extensions.conf 使用传统写法,这个方式最常用

在/etc/asterisk/extensions.ael 里使用Asterisk Extension Logic (AEL)

在/etc/asterisk/extensions.lua里使用lua

连接到pstn需要硬件

第四章 配置

主配置在/etc/asterisk/asterisk.conf 中

可在启动时指定主配置asterisk -C /custom/path/to/asterisk.conf

AGI默认加载文件夹:

astagidir => /var/lib/asterisk/agi-bin

modules.conf  模块加载配置

推荐的做法是,写明不加载的(autoload=yes + noload => xxx)。没必要一条条写明加载的。

indications.conf  语音(方言)配置,DAHDI不使用这个配置。

musiconhold.conf  配置等待音乐

asterisk等待音乐格式是sln结尾文件名,这是因为mp3这样的高压缩格式会消耗cpu性能,所以要转换成低采样率wav格式?

第五章 设备配置

SIP 可以是Peer-to-Peer但对一asterisk来说,是通过asterisk来桥接的。

AST只有通道名的概念,而没有用户的概念,他只关注通道名称,而且,extension在AST里面不仅仅指分机,它的含义是指令集名称。

名称只能由数字字母组成,无空白。推荐使用目标设备mac地址。

最常用的协议时sip和iax(2),配置分别在sip.conf 和 iax.conf中,对应驱动分别是chan_sip.so 和 chan_iax2.so

Freepbx添加sip也是修改的文件sip.conf。

AST加载配置的顺序:

明确指明的块例如: [111]

指定块的模板

[general]

代码硬编码的配置

----

channel配置与dialplan的关系如图:

image

可见dialplan需要使用这些配置来决定接收目标和发送目标。

channel配置不仅控制呼叫进入系统,也控制呼叫怎样离开系统,例如:

1 call 2,channel配置不仅用于传递呼叫到dial plan,而且引导呼叫从dialplan到目标。

 

示例:

[office-phone](!)     ; create a template for our devices

 

[0000FFFF0001](office-phone)

 

从上可见注释使用; ,模板(!), 继承模板(模板名)

udpbindaddr=0.0.0.0            ; listen for UDP requests on all interfaces(0.0.0.0表示所有)

tcpenable=no                            ; disable TCP support(要么tcp,udp都开,要么开一个,不能全部都关)

type的类型:

peer :使用请求的源端ip和端口匹配配置

user:使用请求的From头来匹配配置

支持ipv6

第12章将会介绍dns(srvrecord)

94页到98页缺失

使用AST CLI:

最有用的为,当修改sip或iax配置后,重新加载使配置生效:

asterisk -r

*CLI> module reload chan_sip.so

*CLI> module reload chan_iax2.so

查看状态:

*CLI> sip show peers ;这个显示当前连接、注册状态

*CLI> sip show users  ;这个直接将密码都打出来了,相当于配置信息

*CLI> iax2 show peers

*CLI> iax2 show users

介绍了模拟电话安装,这个需要硬件,还有DAHDI配置。

dialplan重新加载命令:

asterisk -rx "dialplan reload"

*CLI> dialplan reload

背靠背的User Agent:

呼叫流程:sip1 –>asterisk;  asterisk—>sip2

实际是两个呼叫,AST将其桥接,所以叫做back to back(上图中两个AST背靠背)

会话的过程状态可从CLI中看到,这个便于调试dialplan

 

第六章 dial plan基础

四个重要概念contexts, extensions, priorities, applications.

Contex

用于分类组,可用字母数字下划线和连字符组(-)成,不能超过79字符。各context是独立的除非他们互相交互

[general], [default], and [globals]是三个固有的特殊上下文。

image

上图可见context的作用。

Context的最大用途是分配安全策略,见https://wiki.asterisk.org/wiki/display/AST/Important+Security+Considerations

Extensions

这个更像是控制流,定义为:

exten => name,priority,application()

例如exten => 123,1,Answer()

Priorities

如下例:

exten => 123,1,Answer()

exten => 123,2,Hangup()

那么2会在1后执行。

使用n:

exten => 123,1,Answer()

exten => 123,n,do something

exten => 123,n,do something else

exten => 123,n,do one last thing

exten => 123,n,Hangup()

n代表next,就是往下执行的意思,但是注意,1必须有,否则不起作用。

使用 'same =>':

exten => 123,1,Answer()

same => n,do something

same => n,do something else

same => n,do one last thing

same => n,Hangup()

这个一看就知道了怎么用了。

使用Priority labels,这个稍后讲其用途:

exten => 123,n(label),application()

Applications

例如Answer(), Playback(), and Hangup()这些东东。传参数在1.6之前可使用|,从1.6开始就不支持了。

Answer() : 一般是不需要的,但是可以起确保下一步之前已经连接成功的作用。

Progress():一般不需要,向发起端回应当前呼叫状态。

Playback():播放上一次的输出(如果上一次为输入则跳过寻找上一次输出)

Playback(/home/john/sounds/filename) :播放/home/john/sounds/filename.wav 绝对路径

Playback(filename) : 播放/var/lib/asterisk/sounds/filename.wav 默认路径

Playback(custom/filename) 播放/var/lib/asterisk/sounds/custom/filename.wav 相对路径

以上都不能有扩展名。

Background():类似PlayBack但是放音乐同时允许用户输入

Hangup() :

在CLI中运行core show translation 可知道各音频格式转换消耗。

 

对于这样一个hello world

exten => 200,1,Answer()

same => n,Playback(hello-world)

same => n,Hangup()

我测试,可以运行,但是声音很卡。

与用户交互

BackGround https://wiki.asterisk.org/wiki/display/AST/Application_BackGround

与playback类似,但是允许用户输入,WaitExten则等待用户输入。

如下例:

[TestMenu]

exten => start,1,Answer()                                       ;应答

same => n,Background(main-menu)                ;放main-menu.wav并等待用户输入

same => n,WaitExten(5)                                        ;音乐放完了还没有输入则等待用户输入5秒钟

exten => 1,1,Playback(digits/1)                             ;当用户输入1时,播放1按键音

same => n,Goto(TestMenu,start,1)                    ;转到TestMenu

exten => 2,1,Playback(digits/2)                           ;当用户输入2时,播放2按键音

same => n,Goto(TestMenu,start,1)                    ;转到Testmenu

exten => i,1,Playback(pbx-invalid)                      ;i代表其他输入     
same => n,Goto(TestMenu,start,1)

exten => t,1,Playback(vm-goodbye)                     ;t代表超时,用户没有输入

same => n,Hangup()

Dial https://wiki.asterisk.org/wiki/display/AST/Application_Dial

拨出电话,

一般只拨一个号码如 exten => 105,1,Dial(DAHDI/1) ;转拨到DAHDI通道1

也可以一次拨多个 exten => 105,1,Dial(DAHDI/1&SIP/0004F2001122&IAX2/Softphone) ;使用&连接多个通道,但是这个不是电话会议的功能,起作用时,同时拨这三个通道,但是一旦有通道应答,则与之建立连接,其它通道不再响铃。

Dial允许直接拨未配置的远端资源:

Dial(technology/user[:password]@remote_host[:port][/remote_extension])

可以尝试一下Dial(IAX2/guest@misery.digium.com/s) 这个是Digium提供的测试资源。

Dial的第二个参数为超时时间,如果在超时前连接成功,则此dialplan就结束了(失去控制?),如果超时,则向后执行:

exten => 201,1,Dial(DAHDI/1,10)

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

Dial的三个参数是选项,最常用的是m,表示呼叫方在连接之前会听到hold music而不是响铃音。

第四个参数很少用就不讲了

跳过参数:exten => 1,1,Dial(DAHDI/1,,m)  ;这里跳过了第二个参数但设置了第三个参数。

dialplan的变量

exten => 301,1,Set(LEIF=SIP/0000FFFF0001)   ;设置变量LEIF

same => n,Dial(${LEIF})                                                ;引用变量LEIF

变量区分大小写,一般全局变量用全大写,channel变量用驼峰命名法,可使用下划线。

CHANNEL 和 EXTEN是asterisk固有的变量。

全局变量可由所有通道共享,必须定义在globals中:

[globals]

LEIF=SIP/0000FFFF0001

通道变量只在通道中可见,对于参与会话的其他通道也可见:

exten => 202,1,Set(MagicNumber=42)

same => n,SayNumber(${MagicNumber})

环境变量:

${ENV(var)} 获得linux系统环境变量值var是变量名

模式匹配:

以下划线开始:

X 单个0到9的数字

Z 单个1到9的数字

N 单个2到9的数字

[15-7] 方括号, 此例表示1,或是5到7的单个数字

.  一到多个字符,例如:

_.  这个表示所有匹配,一般很少用

_X. 以数字开始的所有字符串

_[0-9a-zA-Z]. 这个就匹配所有的了

! 0到多个字符

多组匹配的情况,会优先选取最精确地(从左到右),例如

exten => _555XXXX,1,Playback(silence/1&digits/1)

exten => _55512XX,1,Playback(silence/1&digits/2)

那么555120会匹配第二个,因为它的精确度高。

匹配示例 127页

这里主要介绍了北美的一些有用的模式,还有NANP:北美号码计划

在dialplan中,可以使用${EXTEN}来获得当前呼叫的号码,这对于使用了匹配的dialplan来说很有用。

${EXTEN:x:y} 的用法

假如呼叫94169671111

• ${EXTEN:1:3}  = 416

• ${EXTEN:4:7}  =  9671111

• ${EXTEN:-4:4}  = 1111    ;最末往前数4位,然后返回此位置向后的四位

• ${EXTEN:2:-4}  = 16967 ;从第2位(0为起始索引)开始,但是排除最末4位

• ${EXTEN:-6:-4}  = 67  ; 最末往前数6位,排除最末4位

• ${EXTEN:1}  = 4169671111 ;第一位之后的

include 语法(注意这与include引导符不一样 #include)

include => context

引入其他context

首先会匹配当前的extention,如果没有匹配再会匹配被引入的context。

详见第七章

Continue reading askterisk笔记【一】

asterisk freepbx freeswitch trixbox elastix freeiris opensips fusionpbx 等等

voip这开源框架太多,都有点糊涂了,这里整理一下他们的关系:

asterisk http://www.asterisk.org/

这个不用多说

freepbx http://www.freepbx.org/

FreePBX 是一个用来控制 Asterisk 的图形化接口。

Elastix http://www.elastix.org/

系统集成了最优秀的工具,它使 Asterisk PBX 拥有一个简单易操作的界面,还增加了自己的设备,允许外界创新,使其成为开源通讯最好的软件包。Elastix 的目标就是要发展成为一个稳定、可调节和易操作的软件系统。这些特点使 Elastix 成为 Asterisk PBX 的首选。

集成SugarCRM和电话计费系统;
集成即时信息服务器 (Openfire);

trixbox http://fonality.com/trixbox/

正是为了解决 Asterisk[1] 难于配置的问题,大约在两年前,Asterisk @Home 项目悄悄地出现了。它提供了日渐完善的一体化安装方案,普通用户也可以在安装向导的指引下,完成从 Linux 系统安装到 PBX 系统配置的全部过程。2006年5月,当 AAH2.8 出现的时候,它已经整合了Asterisk[1]、FreePBX(一套基于Web的 Asterisk[1] 配置管理系统)、MySQL 和 SugarCRM[2]。在全球范围内得到了包括企业和行业用户在内的广泛用户支持。在这种形式下,社区的主要开发者开始谋求改变 AAH的本名和原定位,将 AAH 发展成一个真正的产品,于是,Trixbox1.0 产生了。2006年10月,VoIP 产品和解决方案提供商 Fonality 并购了Trixbox,使其有了进一步发展的坚实后盾。

需要指出的是,Trixbox 并不是简单地把 Asterisk 和 SugarCRM[2] 叠加在了一起,而是进行了深层次的整合,例如,在 SugarCRM [2]中,只要点击客户的电话号码,VoIP 客户端软件就能够自动进行拨号动作。

freeiris http://www.freeiris.org

Freeiris(前身为Astercon2)是一款开源的电话通信平台,含盖了计费、注册管理、PBX、数字中继、呼叫中心等业务需要。系统基于Asterisk、Perl、Linux、PHP等技术实现,在不修 改asterisk本身的情况下采用外挂形式开发。目前系统可以控制管理SIP、IAX、H323、等软协议的通信。在硬件层上,支持大量的硬件产品,包 括数字中继(ISDN PRI / ISDN BRI),模拟中继(FXO / FXS),以及各种SIP与IAX的终端设备等

似乎是国人写的

SER,OpenSER  http://www.iptel.org/ser/

这个真有点昏,SER一般指Openser,现在停止开发了,而由在其基础上又出现两个开源框架Kamailio 和 OpenSIPS 。

目前有SER+Asterisk组合,就是让SER承担SIP路由部分。

Kamailio http://www.kamailio.org/w/

参见SER

OpenSIPS http://www.opensips.org/

OpenSIPS是一个成熟的开源SIP服务器,除了提供基本的SIP代理及SIP路由功能外,还提供了一些应用级的功能。OpenSIPS的结构非常灵活,其核心路由功能完全通过脚本来实现,可灵活定制各种路由策略,可灵活应用于语音、视频通信、IM以及Presence等多种应用。同时OpenSIPS性能上是目前最快的SIP服务器之一,可用于电信级产品构建。

FreeSWITCH http://www.freeswitch.org/

FreeSWITCH 是一个开源的电话交换平台,从一个简单的软电话客户端到运营商级的软交换设备几乎无所不能。能原生地运行于Windows、Max OS X、Linux、BSD 及 solaris 等诸多32/64位平台。可以用作一个简单的交换引擎、一个PBX,一个媒体网关或媒体支持IVR的服务器等。它支持SIP、H323、Skype、Google Talk等协议,并能很容易地与各种开源的PBX系统如sipXecs、Call Weaver、Bayonne、YATE及Asterisk等通信。 FreeSWITCH 遵循RFC并支持很多高级的SIP特性,如 presence、BLF、SLA以及TCP、TLS和sRTP等。它也可以用作一个SBC进行透明的SIP代理(proxy)以支持其它媒体如T.38等。FreeSWITCH 支持宽带及窄带语音编码,电话会议桥可同时支持8、12、16、24、32及48kHZ的语音. 而在传统的电话网络中,要做到三方通话或多方通话需要通过专门的芯片来处理,其它像预付费,彩铃等业务在PSTN网络中都需要依靠智能网(IN)才能实现,而且配置起来相当不灵活

fusionpbx  http://www.fusionpbx.com/

fusionpbx是freeswitch图形WEB接口

 

搞清楚了,原来说白了就三大家族asterisk和freeswich另加SER系列的。 而且freeswitch和asterisk还是有些渊源的。 参见http://blog.ureshika.com/archives/869.html

Continue reading asterisk freepbx freeswitch trixbox elastix freeiris opensips fusionpbx 等等

【转】FreeSWITCH 与 Asterisk(译)

PS:才对asterisk感兴趣,freeswich的声音又多起来了……

转自http://www.dujinfang.com/past/2010/1/22/freeswitch-yu-asteriskyi/ 

 

Anthony Minssale/文 Seven/译

VoIP通信,与传统的电话技术相比,不仅仅在于绝对的资费优势,更重要的是很容易地通过开发相应的软件,使其与企业的业务逻辑紧密集成。Asterisk作为开源VoIP软件的代表,以其强大的功能及相对低廉的建设成本,受到了全世界开发者的青睐。而FreeSWITCH作为VoIP领域的新秀,在性能、稳定性及可伸缩性等方面则更胜一筹。本文原文在http://www.freeswitch.org/node/117, 发表于2008年4月,相对日新月异的技术来讲,似乎有点过时。但本文作为FreeSWITCH背后的故事,仍很有翻译的必要。因此,本人不揣鄙陋,希望与大家共读此文,请不吝批评指正。 --译者注

FreeSWITCH 与 Asterisk 两者有何不同?为什么又重新开发一个新的应用程序呢?最近,我听到很多这样的疑问。 为此,我想对所有在该问题上有疑问的电话专家和爱好者们解释一下。我曾有大约三年的时间用在开发 Asterisk 上,并最终成为了 FreeSWITCH 的作者。因此,我对两者都有相当丰富的经验。首先,我想先讲一点历史以及我在 Asterisk 上的经验;然后,再来解释我开发FreeSWITCH的动机以及我是如何以另一种方式实现的。

我从2003年开始接触 Asterisk,当时它还不到1.0版。那时对我来讲,VoIP还是很新的东西。我下载并安装了它,几分钟后,从插在我电脑后面的电话机里传出了电话拨号音,这令我非常兴奋。接下来,我花了几天的时间研究拨号计划,绞尽脑汁的想能否能在连接到我的Linux PC上的电话上实现一些好玩的东西。由于做过许多Web开发,因此我积累了好多新鲜的点子,比如说根据来电显示号码与客户电话号码的对应关系来猜想他们为什么事情打电话等。我也想根据模式匹配来做我的拨号计划,并着手编写我的第一个模块。最初,我做的第一个模块是app_perl,现在叫做res_perl,当时曾用它在Asterisk中嵌入了一个Perl5的解释器。现在我已经把它从我的系统中去掉了。

后来我开始开发一个Asterisk驱动的系统架构,用于管理我们的呼入电话队列。我用app_queue和现在叫做AMI(大写字母总是看起来比较酷)的管理接口开发了一个原型。它确实非常强大。你可以从一个T1线路的PSTN号码呼入,并进入一个呼叫队列,坐席代表也呼入该队列,从而可以对客户进行服务。非常酷!我一边想一边看着我的可爱的Web页显示着所有的队列以及他们的登录情况。并且它还能周期性的自动刷新。令人奇怪的是,有一次我浏览器一角上的小图标在过了好长时间后仍在旋转。那是我第一次听说一个词,一个令我永远无法忘记的词 -- 死锁。

那是第一次,但决不是最后一次。那一天,我几乎学到了所有关于GNU调试器的东西,而那只是许多问题的开始。队列程序的死锁,管理器的死锁。控制台的死锁开始还比较少,后来却成了一个永无休止的过程。现在,我非常熟悉“段错误(Segmentation Fault)”这个词,它真是一个计算机开发者的玩笑。经过一年的辛勤排错,我发现我已出乎意料的非常精通C语言并且有绝地战士般的调试技巧。我有了一个分布于七台服务器、运行于DS3 TDM信道的服务平台。与此同时,我也为这一项目贡献了大量的代码,其中有好多是我具有明确版权的完整文件(http://www.cluecon.com/anthm.html)。

到了2005年,我已经俨然成了非常有名的Asterisk开发者。他们甚至在CREDITS文件以及《Asterisk,电话未来之路》这本书中感谢我。在Asterisk代码树中我不仅有大量的程序,而且还有一些他们不需要或者不想要的代码,我把它们收集到了我的网站上。(至今仍在 http://www.freeswitch.org/node/50)

Asterisk 使用模块化的设计方式。一个中央核心调入称为模块的共享目标文件以扩展功能。模块用于实现特定的协议(如SIP)、程序(如个性化的IVR)和其它外部接口(如管理接口)等。 Asterisk的核心是多线程的,但它非常保守。仅仅用于初始化的信道以及执行一个程序的信道才有线程。任何呼叫的B端都与A端都处于同一线程。当某些事件发生时(如一次转移呼叫必须首先转移到一个称作伪信道的线程模式),该操作把一个信道所有内部数据从一个动态内存对象中分离出来,放入另一个信道中。它的实现在代码注释中被注明是“肮脏的”[1]。反向操作也是如此,当销毁一个信道时,需要先克隆一个新信道,才能挂断原信道。同时也需要修改CDR的结构以避免将它视为一个新的呼叫。因此,对于一个呼叫,在呼叫转移时经常会看到3或4个信道同时存在。

这种操作成了从另一个线程中取出一个信道事实上的方法,同时它也正是开发者许许多多头痛的源头。这种不确定的线程模式是我决定着手重写这一应用程序的原因之一。

Asterisk使用线性链表管理活动的信道。链表通过一种结构体将一系列动态内存串在一起,这种结构体本身就是链表中的一个成员,并有一个指针指向它自己,以使它能链接无限的对象并能随时访问它们。这确实是一项非常有用的编程技术,但是,在多线程应用中它非常难于管理。在线程中必须使用一个信号量(互斥体,一种类似交通灯的东西)来确保在同一时刻只有一个线程可以对链表进行写操作,否则当一个线程遍历链表时,另一个线程可能会将元素移出。甚至还有比这更严重的问题 ─ 当一个线程正在销毁或监听一个信道的同时,若有另外一个线程访问该链表时,会出现“段错误”。“段错误”在程序里是一种非常严重的错误,它会造成进程立即终止,这就意味着在绝大多数情况下会中断所有通话。我们所有人都看到过“防止初始死锁”[2]这样一个不太为人所知的信息,它试图锁定一个信道,在10次不成功之后,就会继续往下执行。

管理接口(或AMI)有一个概念,它将用于连接客户端的套接字(socket)传给程序,从而使你的模块可以直接访问它。或者说,更重要的是你可以写入任何你想写入的东西,只要你所写入的东西符合Manager Events所规定的格式(协议)。但遗憾的是,这种格式没有很好的结构,因而很难解析。

Asterisk的核心与某些模块有密切的联系。由于核心使用了一些模块中的二进制代码,当它所依赖的某个模块出现问题,Asterisk就根本无法启动。如果你想打一个电话,至少在 Asterisk 1.2中,除使用app_dial和res_features外你别无选择,这是因为建立一个呼叫的代码和逻辑实际上是在app_dial中,而不是在核心里。同时,桥接语音的顶层函数实际上包含在res_features中。

Asterisk的API没有保护,大多数的函数和数据结构都是公有的,极易导致误用或被绕过。其核心非常混乱,它假设每个信道都必须有一个文件描述符,尽管实际上某些情况下并不需要。许多看起来是一模一样的操作,却使用不同的算法和杰然不同的方式来实现,这种重复在代码中随处可见。

这仅仅是我在Asterisk中遇到的最多的问题一个简要的概括。作为一个程序员,我贡献了大量的时间,并贡献了我的服务器来作为CVS代码仓库和Bug跟踪管理服务器。我曾负责组织每周电话会议来计划下一步的发展,并试图解决我在上面提到过的问题。问题是,当你对着长长的问题列表,思考着需要花多少时间和精力来删除或重写多少代码时,解决这些问题的动力就渐渐的没有了。值得一提的是,没有几个人同意我的提议并愿意同我一道做一个2.0的分支来重写这些代码。所以在2005年夏天我决定自己来。

在开始写FreeSWITCH时,我主要专注于一个核心系统,它包含所有的通用函数,即受到保护又能提供给高层的应用。像Asterisk一样,我从Apache Web服务器上得到很多启发,并选择了一种模块化的设计。第一天,我做的最基本的工作就是让每一个信道有自己的线程,而不管它要做什么。该线程会通过一个状态机与核心交互。这种设计能保证每一个信道都有同样的、可预测的路径和状态钩子,同时可以通过覆盖向系统增加重要的功能。这一点也类似其它面向对象的语言中的类继承。

做到这点其实不容易,容我慢慢讲。在开发FreeSWITCH的过程中我也遇到了段错误和死锁(在前面遇到的多,后来就少了)。但是,我从核心开始做起,并从中走了出来。由于所有信道都有它们自己的线程,有时候你需要与它们进行交互。我通过使用一个读、写锁,使得可以从一个散列表(哈希)中查找信道而不必遍历一个线性链表,并且能绝对保证当一个外部线程引用到它时,一个信道无法被访问也不能消失。这就保证了它的稳定,也不需要像Asterisk中“Channel Masquerades”之类的东西了。

FreeSWITCH核心提供的的大多数函数和对象都是有保护的,这通过强制它们按照设计的方式运行来实现。任何可扩展的或者由一个模块来提供方法或函数都有一个特定的接口,从而避免了核心对模块的依赖性。

整个系统采用清晰分层的结构,最核心的函数在最底层,其它函数分布在各层并随着层数和功能的增加而逐渐减少。

例如,我们可以写一个大的函数,打开一个任意格式的声音文件向一个信道中播放声音。而其上层的API只需用一个简单的函数向一个信道中播放文件,这样就可以将其作为一个精减的应用接口函数扩展到拨号计划模块。因此,你可以从你的拨号计划中,也可以在你个性化的C程序中执行同样的playback函数,甚至你也可以自己写一个模块,手工打开文件,并使用模块的文件格式类服务而无需关注它的代码。

FreeSWITCH由几个模块接口组成,列表如下:

拨号计划(Dialplan): 实现呼叫状态,获取呼叫数据并进行路由。

终点(Endpoint): 为不同协议实现的接口,如SIP,TDM等。

自动语音识别/文本语音转换(ASR/TTS): 语音识别及合成。

目录服务(Directory): LDAP类型的数据库查询。

事件(Events): 模块可以触发核心事件,也可以注册自己的个性事件。这些事件可以在以后由事件消费者解析。

事件句柄(Event handlers): 远程访问事件和CDR。

格式(Formats): 文件模式如wav。

日志(Loggers): 控制台或文件日志。

语言(Languages): 嵌入式语言,如Python和JavaScript。

语音(Say): 从声音文件中组织话语的特定的语言模块。

计时器(Timers): 可靠的计时器,用于间隔计时。

应用(Applications): 可以在一次呼叫中执行的程序,如语音信箱(Voicemail)。

FSAPI(FreeSWITCH 应用程序接口) 命令行程序,XML RPC函数,CGI类型的函数,带输入输出原型的拨号计划函数变量。

XML 到核心XML的钩子可用于实时地查询和创建基于XML的CDR。

所有的FreeSWITCH模块都协同工作并仅仅通过核心API或内部事件相互通信。我们非常小心地实现它以保证它能正常工作,并避免其它外部模块引起不期望的问题。

FreeSWITCH的事件系统用于记录尽可能多的信息。在设计时,我假设大多数的用户会通过一个个性化的模块远程接入FreeSWITCH来收集数据。所以,在FreeSWITCH中发生的每一个重要事情都会触发一个事件。事件的格式非常类似于一个电子邮件,它具有一个事件头和一个事件主体。事件可被序列化为一个标准的Text格式或XML格式。任何数量的模块均可以连接到事件系统上接收在线状态,呼叫状态及失败等事件。事件树内部的mod_event_socket可提供一个TCP连接,事件可以通过它被消费或记入日志。另外,还可以通过此接口发送呼叫控制命令及双向的音频流。该套接字可以通过一个正在进行的呼叫进行向外连接(Outbound)或从一个远程机器进行向内(Inbound)连接。

FreeSWITCH中另一个重要的概念是中心化的XML注册表。当FreeSWITCH装载时,它打开一个最高层的XML文件,并将其送入一个预处理器。预处理器可以解析特殊的指令来包含其它小的XML文件以及设置全局变量等。在此处设置的全局变量可以在后续的配置文件中引用。

如,你可以这样用预处理指令设置全局变量:

<X-PRE-PROCESS cmd="set" data="moh_uri=local_stream://moh"/>

现在,在文件中的下一行开始你就可以使用 $$(moh_uri},它将在后续的输出中被替换为 local_stream://moh。处理完成后XML注册表将装入内存,以供其它模块及核心访问。它有以下几个重要部分:

配置文件: 配置数据用于控制程序的行为。

拨号计划: 一个拨号计划的XML表示可以用于 mod_dialplan_xml,用以路由呼叫和执行程序。

分词: 可标记的IVR分词是一些可以“说”多种语言的宏。

目录: 域及用户的集合,用于注册及账户管理。

通过使用XML钩子模块,你可以绑定你的模块来实时地查询XML注册表,收集必要的信息,以及返回到呼叫者的静态文件中。这样你可以像一个WEB浏览器和一个CGI程序一样,通过同一个模型来控制动态的SIP注册,动态语音邮件及动态配置集群。

通过使用嵌入式语言,如Javascript, Java, Python和Perl等,可以使用一个简单的高级接口来控制底层的应用。

FreeSWITCH工程的第一步是建立一个稳定的核心,在其上可以建立可扩展性的应用。我很高兴的告诉大家在2008年5月26日将完成FreeSWITCH 1.0 PHOENIX版。有两位敢吃螃蟹的人已经把还没到1.0版的FreeSWITCH 用于他们的生产系统。根据他们的使用情况来看,我们在同样的配置下能提供Asterisk 10倍的性能。

我希望这些解释能足够概括FreeSWICH和Asterisk的不同之处以及我为何决定开始FreeSWITCH项目。我将永远是一个Asterisk开发者,因为我已深深的投入进去。并且,我也希望他们在以后的Asterisk开发方面有新的突破。我甚至还收集了很多过去曾经以为已经丢失的代码,放到我个人的网站上供大家使用, 也算是作为我对引导我进入电话领域的这一工程的感激和美好祝愿吧。

Asterisk是一个开源的PBX,而FreeSWITCH则是一个开源的软交换机。与其它伟大的软件如 Call Weaver、Bayonne、sipX、OpenSER以及更多其它开源电话程序相比,两者还有很大发展空间。我每年都期望能参加在芝加哥召开的 ClueCon大会,并向其它开发者展示和交流这些项目(http://www.cluecon.com)。

我们所有人都可以相互激发和鼓励以推进电话系统的发展。你可以问的最重要的问题是:“它是完成该功能的最合适的工具吗?”

[1] / XXX This is a seriously wacked out operation. We're essentially putting the guts of the clone channel into the original channel. Start by killing off the original channel's backend. I'm not sure we're going to keep this function, because while the features are nice, the cost is very high in terms of pure nastiness. XXX /

[2] Avoiding initial deadlock

 

PS:摘抄网上的:

1:Asterisk是针对百人左右的小型系统,相同的硬件配置下单系统并发也就几百路(不同版本性能有一定差异,大概在 200-400之间),而根据国外爱好者测试freeswitch 可达到2000-3000路sip通道(媒体流并发),

2:Asterisk用动态链表来管理每个打开的通道,这样在多线程中非常难于管理(需要频繁的锁定和解锁)。而freeswitch每个呼叫通道都会用一个线程来管理呼叫状态,大大减少了死锁发生的几率,freeswitch核心代码高度抽象,尽量将复杂代码集中化。

3:Asterisk用DUNDi协议设计分布式系统,Fs使用外部数据库实现分布系统,做得更好,甚至可以一台服务器通过数据库注册到另一台服务器上。

4:freeswitch 支持夸平台,linux, unix, windows 等,asterisk基本只支持 linux, bsd系列。

5. freeswitch配置采用xml,asterisk采用linux下面通用配置文件格式语法,而 采用xml格式配置文件是freeswich使用者抱怨最多的部分,对于不懂xml格式的开发者在刚开始使用时是个折磨。

Continue reading 【转】FreeSWITCH 与 Asterisk(译)

Eclipse Tomcat配置Web项目

现在越来越感到jee版本要求越来越高,我最顺手的myeclipse6 渐渐会碰到越来越多的兼容问题,是时候改用高版本eclipse了。

以前用WASD6来开发,最要命的就是部署web,那个真是没有myeclipse的发布方便。

这个eclipse里的WTP似乎就是WASD里面得东西(Eclipse本身就是IBM贡献的),特不好用。

这次记一下,以免忘记了。

配置Tomcat我就不细说了,在servers中New一个,这个简单。

主要是添加web项目属性:

Snap2

注意选择版本,可看到上图中的警告,web mudule3.0需要jdk6以上。

再就是,web根目录默认是WebContent,这个似乎是和WSAD一样的。我还没试过哪里可以改这个选项。

然后就可以通过Servers里面配置的Tomcat来Publish,Start,Stop项目了。

这里Tomcat运行的目录并不是Tomcat安装目录下的webapps,而在Eclipse工作区

/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps 中

 

参见:

http://www.cnblogs.com/jspace/archive/2011/04/04/2004947.html

http://blog.csdn.net/suixingbugai/article/details/6238526

Continue reading Eclipse Tomcat配置Web项目

ATT SDK 使用笔记

这两天试用了下ATT SDK, https://devconnect-api.att.com/用武汉话总结—稀烂.

1 每个开发组织(每个组织下可有多个开发者)每年要99美刀,这个倒是和苹果看齐了,还没开始先宰你一刀。

2 我尝试SMS 和 MMS,结果发现只支持ATT 用户,这是文档上写明了的。

3 还没发现call 的api。

4 奇怪的oath。步骤比较复杂。它的示例代码getToken.jsp还有bug。

SpeechToText Api结果加入了语义分析结果,例如_PHONE (123)256-7890. _END_PHONE,这简直被驴踢了。如果想要原始结果还要自己写代码去掉。 其结果比Nuance Dragon差:

1 花费时间要长, 估计是花在web seartch上了

2 翻译结果没有Nuance精确。我怀疑它这就是用的Nuance。

3 一般只返回一个结果。

Continue reading ATT SDK 使用笔记

Worspress SyntaxHighlighter代码着色

wordpress有插件,但是我们一般都是用wlw来写文章,所以还得用wlw的插件:

wlw插件下载地址即配置说明:http://wlwsyntaxhighlighter.codeplex.com/

测试一下:

<?php
echo "hello world";	
?>

步骤是安装wlw插件,

wlw同步主题:日志/编辑日志设置/编辑/刷新主题

然后将https://code.google.com/p/syntaxhighlighter中的资源上传到你的wp中,还要在你的主题中添加代码:

<link type="text/css" rel="stylesheet" href="Styles/SyntaxHighlighter.css"></link>
<script language="javascript" src="Scripts/shCore.js"></script>
<script language="javascript" src="Scripts/shBrushCSharp.js"></script>
<script language="javascript">
window.onload = function() {
    dp.SyntaxHighlighter.ClipboardSwf = 'Scripts/clipboard.swf';
    dp.SyntaxHighlighter.HighlightAll('code');
};
 </script>

稍微有点麻烦。

 

Continue reading Worspress SyntaxHighlighter代码着色

使用Spring开发RESTful API

使用spring mvc可以实现RESTful API。这次不得不用spring,我发现我的博客里一篇spring的笔记都没有!

现在还是从头来吧。

官方文档:

http://static.springsource.org/spring/docs/

http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html

官方pdf下载地址: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/pdf/spring-framework-reference.pdf

 

/ 和/*的区别:

/是默认的servlet配置(就是没有被其映射截获的都会被这个处理,包含静态资源),而/*则完全包括了所有的路劲。

http://tomcat.apache.org/tomcat-7.0-doc/default-servlet.html

 

开始就犯个错:

copy网上的

<context:component-scan base-package="xxx.*>  </context:component-scan>

结果一直无法映射,xxx包里的类根本没加载,再看文档,没那里说支持*,(有的blog里面甚至还有***).改为

<context:component-scan base-package="xxx”>  </context:component-scan>就可以了。我看还是直接看文档最靠谱.

 

关于mapping的问题

A类配置了根/abc/

B类则不能配置根为/abc/efg,配置了虽不报错也无效

那么只好在A类里配置/efg到方法中

 

关于springmvc配置和spring配置

注意springmvc的配置应该和spring的配置分开,spring的配置是指关于spring 核心功能的配置,springmvc则应该视为web mvc架构的spring实现,例如springmvc中的注解只会应用mvc相关的功能例如controller,会忽略你在其配置中配置的其他像transaction注解,甚至覆盖service注解等

所以应该在web.xml的listener中加载spring配置,而在web.xml中servlet中配置springmvc配置。而且springmvc控制器类应该和业务功能严格分离,这就要求你的springmvc控制器不能有transaction,service等注解,你必须将业务逻辑分离出来由控制器调用。

 

这个问题坑了我一把,我在springmvc中配置tranaction事务注解,结果事务注解总是没起作用,而spring却什么错误提示也没有,着实挖了个大坑。

参见:

http://stackoverflow.com/questions/10019426/spring-transactional-not-working

 

关于ServletContext

3.0之前可以使用ApplicationContextAware接口来获得WebApplicationContext,通过它来获得Servletcontext。

也可以这样:

<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>

 

那么这个ServletContextFactoryBean就可以获得Servletcontext。

 

3.0之后servletContext默认就是存在Spring中的Bean,直接引用即可。

 

 

配置示例:

class="c#" name="code"><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-application.xml</param-value> </context-param>

Continue reading 使用Spring开发RESTful API

Pagination


Total views.

© 2013 - 2024. All rights reserved.

Powered by Hydejack v6.6.1