第二篇:利用shell脚本执行webservice请求——基于soap
1. 项目背景
以往我们在开发基于webservice的项目中,我们总习惯于直接使用webservice的一些框架,如Axis,axis2和Xfire等。框架的好处是将webservice所涉及到的soap协议、wsdl以及uddi都封装起来,我们只需要直接调用方法传值并执行请求就可以。但框架也有缺陷,比如axis2要基于java工程,哪怕只是一个简单的功能我们都要搭建一个java web项目去实现它。这样做的后果就是:
1. 占用服务器磁盘资源(一个java web项目至少也要几M);
2. 占用内存资源。特别是对那些不需要页面的项目来说,java web实在是大材小用了。
就拿我最近开发的短信定时发送项目为例。在这个项目里,我们只需要每天从数据库取数据然后拼成短信,定时调用总公司的短信接口发送短信就可以了。不需要任何图形界面,功能也很单一,如果用java项目去做就太小题大做了。所以我们想到一个巧妙的办法,直接利用webservice的底层知识去实现这个功能。即直接用Linux的shell脚本生成soap消息,然后用soap请求webservice。
2. 实施过程
2.1项目分析
上文提到的短信项目是一个为了实现我们公司办公信息化的小项目。其主要功能就是每天从数据库读取分公司即各支公司保费收入及业务达成情况,然后组合成短信发给各个领导以便于其合理调整公司发展策略。
这个项目有两个特点:
1. 功能比较单一;
2. 不需要图形界面操作。因此我们完全可以抛开java项目,直接用shell脚本去实现。
2.2实现流程
2.2.1 技术介绍
在介绍实现过程之前我们先介绍下soap协议。Soap协议全称为simple Object Access Protocol,是一个基于http的访问协议,这里的simple Object指代就是soap消息,它本质上是一个xml格式的文件,必须包含以下元素:
* 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
* 可选的 Header 元素,包含头部信息
* 必需的 Body 元素,包含所有的调用和响应信息
* 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息
同时soap协议还要基于POST请求,因为post请求有body域,可以用来封装soap消息。
Soap请求的方式有很多种,可以在框架中请求(后文中有介绍,直接封装在框架中,用户只要传值就可以)。也可以自己基于格式编写soap消息,直接用http命令请求,比如Linux的curl命令。相对来说后者的效率会更高些。
2.3.2 具体实现
2.3.2.1 soap消息生成工具脚本
由于soap消息是一个有固定格式的xml文件,因此我们可以用工具脚本去生成。其代码如下所示:
#!/bin/bash
# filename: create_xml.sh
# create_MarsCheng_20160922
# 从外部传入的第一个参数作为xml的文件名
outfile=$1
# xml中的缩进位
tabs=0
# ++++++++++++++++++++++++++++
# 组装一个节点,输出到文件
# 说一说传参数时的这几个区别:假如有下面这个脚本执行的命令
# /path/to/scriptname opt1 opt2 opt3 opt4
# $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
# $# :代表后接的参数『个数』
# $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
# $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
# 在shell中我们可以也可以使用${}包含变量名,来调用变量
# ++++++++++++++++++++++++++++
put(){
echo '<'${*}'>' >> /tmp/sms/request/$outfile
}
# 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
# ${@:3} 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
put_tag() {
echo '<'${1}' xsi:type="'${2}'">'${@:3}'</'${1}'>' >> /tmp/sms/request/$outfile
}
# 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
put_tag_cdata() {
echo '<'${1}' xsi:type="'${2}'"><![CDATA['${@:3}']]></'${1}'>' >> /tmp/sms/request/$outfile
}
#由于soap消息的头部一部分一般固定,因此可以直接写一个固定的方法输出
put_head(){
echo –e “…”>> /tmp/sms/request/$outfile
}
#由于soap消息的尾部一部分一般固定,因此可以直接写一个固定的方法输出
put_end(){
echo –e “…”>> /tmp/sms/request/$outfile
}
tag_start(){
str=""
str=${1}' xsi:type="'${2}'"'
put $str
}
tag_start_array(){
str=""
str=${1}' q1:arrayType="'${2}'" xsi:type="q1:Array"'
put $str
}
tag() {
str=""
str=${1}' xsi:type="'${2}'" /'
put $str
}
tag_value(){
if [ "$1" == 0 ]
then
put_tag ${2} ${3} $(echo ${@:4})
elif [ "$1" == 1 ]
then
put_tag_cdata ${2} ${3} $(echo ${@:4})
fi
}
tag_end(){
put '/'${1}
}
2.3.2.2具体执行脚本
具体执行请求的脚本,在这个脚本里会调用soap消息生成工具脚本,会连接数据库读取短信内容,最后用curl实现soap请求。
#统计日期,即当前日期前一天
cal_date=$(date -d -1day +%Y-%m-%d)
#短信是否发送标记,若为1则表示短信已发送,否则为0
flag=$(sqlplus -S statistic/123@tjfxdb << EOF
set heading off feedback off pagesize 0 verify off echo off
select flag from statistic.smsflg where calDate ='$cal_date';
commit;
quit;
EOF)
if [ ! -n "$flag" ];
then
#从数据库取出短信内容,存入smsinfo
smsinfo=$(sqlplus -S statistic/123@tjfxdb << EOF
set heading off feedback off pagesize 0 verify off echo off
select smsinfo from statistic.smsInfo where calDate =date'$cal_date' and smscode ='AHYZ' and bvalid = 1 ;
commit;
quit;
EOF)
if [ ! -n "$smsinfo" ]; #若短信内容为空,不发送
then
echo $(date "+%Y-%m-%d %H:%M:%S")" The content is not ready.">> /tmp/sms/log/$cal_date'.log'
else
#生成soap xml文件名
file_name='request'$(date "+%Y%m%d%H%M%S")'.xml'
#调用xml的生成脚本
source '/tmp/sms/create_xml.sh' $file_name
put_head
taskID=$(date "+%s")
declare -i message_size=1
declare -i labels_size=4
name=('DEPTCODE' 'CUR_DATE' 'FUN_DESC' 'CONTENT')
value[0]='123456'
value[1]=$cal_date'日'
value[2]='保费达成情况'
value[3]=$smsinfo
#短信发送对象
telephone=(‘12345678')
message_str2='q2:SmsMessage['$message_size']'
label_str2='q2:Label['$labels_size']'
tag_start_array 'messages' $message_str2
declare -i j=0
#短信核心主体
while ((j<message_size))
do
tag_start 'SmsMessage' 'q2:SmsMessage'
tag_value 0 'packetLength' 'xsd:int' '0'
tag_value 0 'contents' 'xsd:string' '中国人寿'
tag_start_array 'labels' $label_str2
declare -i i=0
while ((i<labels_size))
do
tag_start 'Label' 'q2:Label'
tag_value 0 'packetLength' 'xsd:int' '0'
tag_value 0 'labelName' 'xsd:string' ${name[i]}
if [ $i == 3 ]
then
tag_value 1 'labelValue' 'xsd:string' ${value[i]}
else
tag_value 0 'labelValue' 'xsd:string' ${value[i]}
fi
tag_end 'Label'
let i++
done
tag_end 'labels'
tag_value 0 'orgCode' 'xsd:string' '123456'
tag_value 0 'receiver' 'xsd:string' ${telephone[j]}
tag_end 'SmsMessage'
let j++
done
tag_end 'messages'
tag_value 0 'taskId' 'xsd:string' $taskID
put_end
#请求webservice服务发送短信
curl -H "Content-Type: text/xml;charset=UTF-8" -H "SOAPAction: "http://WebXml.com.cn/getStockInfoByCode"" -d @/tmp/sms/request/$file_name http://Xxxxxxxxxx >> /tmp/sms/log/$cal_date'.log'
#写短信发送标记位
sqlplus -S statistic/123@tjfxdb << EOF
set heading off feedback off pagesize 0 verify off echo off
insert into smsflg(caldate,flag) values('$cal_date',1);
commit;
quit;
EOF
分析:
curl是一个利用URL规则在命令行下工作的文件传输工具,它支持文件的上传和下载,因此在脚本中我们用它来进行soap请求。其命令格式如下。
-H后面跟的是http请求头,’SOAPAction’键通常用来表示这个HTTP请求是一个web服务请求,同时取值可以为空字符串,但是也可以是请求的web服务操作的名称。
2.3.2.3定时执行
为了让系统更加智能化,执行脚本可以加入Linux的crontab定时任务当中。
40 10-18 * * * root sh /tmp/sms/sms_send.sh
上面表示每天10点到18点的40分,脚本都会启动一次,因为在执行脚本中我们加了短信发送标志位,因此不用担心短信回重复发送。
3. 经验总结
Webservice接口的请求方式有很多种,可以通过框架请求,也可以在java项目中直接基于soap请求,还可以像我们这样直接用shell脚本来完成请求。不同的方式有不同的优缺点,我们在实际项目中要学会灵活选择,适合的才是最好的。
第二篇:利用shell脚本执行webservice请求——基于soap的更多相关文章
- 利用shell脚本将Oracle服务器中数据定时增量刷新到ftp服务器中
现有需求:将oracle数据库中的数据准实时同步至某ftp服务器中,以便前端应用能定时从ftp服务器目录中取增量数据 方法:将加工脚本写为存储过程,然后利用shell脚本执行该存储过程并将增量数据导出 ...
- 利用shell脚本实现计划任务功能 V1.2
2013.05.10 mytask 1.2 主程序休眠时间分成若干小的时间片断分段休眠,避免长时间的休眠不能及时响应系统信号. 2013.05.07 mytask 1.1 昨天发布了mytask1. ...
- 利用shell脚本或者php移动某个文件夹下的文件到各自的日期组成的目录下
背景是这样的:网站一开始访问量比较小,大家就把所有的图片文件上传到一个目录下(比如是/data/images/).后来访问量大了,图片也多了,这样就影响读取效率.所以有个这样的需求,把这些个图片文件移 ...
- 利用shell脚本个性化运行jar任务
利用shell脚本可以个性化运行jar任务,废话不多说,直接上代码: #!/bin/bash APP_PATH=/root/bigdata/jars/data_migration_from_sqlse ...
- 利用shell脚本去备份幸运28源码搭建下载所指定的数据库
#! /bin/bash幸运28源码搭建下载Q[115288oo99]logintool=/home/yx/server/mysql/mysql/bin/mysqldumptool=/home/yx/ ...
- (第二篇)shell的简单了解
Shell (类似开发工具) Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程 ...
- windows下建立文件的换行符^M导致linux下的shell脚本执行错误的解决方式
常常在windows下编辑的文件远程传送到linux下的时候每行末尾都会出现^M.这将导致shell脚本执行错误,主要是由于dos下的编辑器和linux下的编辑器对文件末行的回车符处理不一致导致. 主 ...
- 远程shell脚本执行工具类
/** * 远程shell脚本执行工具类 */public class RemoteShellExecutorUtils { private static final Logger logger = ...
- shell脚本执行错误 $'\r':command not found
shell脚本执行错误 $'\r':command not found Linux下有命令dos2unix 可以用一下命令测试 vi -b filename 我们只要输入dos2unix *.sh就可 ...
随机推荐
- 【BZOJ1934】善意的投票(网络流)
[BZOJ1934]善意的投票(网络流) 题面 Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己 ...
- MySQL根据出生日期计算年龄的五种方法比较
方法一 SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(birthday)), '%Y')+0 AS age 方法一,作者也说出了缺陷,就是当日 ...
- 1.4 如何在main()方法之前执行输出“hello world”
public class Test{ static{ System.out.println("hello world"); } public static void main(St ...
- 云计算之路-阿里云上:3个manager节点异常造成 docker swarm 集群宕机
今天 11:29 - 11:39 左右,docker swarm 集群 3 个 manager 节点同时出现异常,造成整个集群宕机,由此给您带来很大的麻烦,请您谅解. 受此次故障影响的站点有:博问,闪 ...
- 百度定位一直出现4.9E -324的问题解决方法
问题:华为mate10一直在申请百度定位的时候出现此问题并且定位权限和定位服务都打开的情况也是返回这个参数 明显没有定位成功,其他手机暂时没有出现(只要打开定位权限就会立即定位成功) 解决:在定位之前 ...
- Zabbix 监控 Docker容器
我们可以通过Python提供的模块docker来取各个docker容器的监控参数.参考文档:http://docker-py.readthedocs.io/en/stable/containers.h ...
- 关系型数据库工作原理-高速缓存(翻译自Coding-Geek文章)
本文翻译自Coding-Geek文章:< How does a relational database work>. 原文链接:http://coding-geek.com/how-dat ...
- 设计模式——装饰器模式(C++实现)
#include <iostream> #include <string> using namespace std; class Component { public: ; } ...
- linux编程基础汇总贴
linux编程基础汇总贴http://newzol.cn/forum.php?mod=viewthread&tid=67&fromuid=3(出处: newzol) 1.管道 http ...
- MySQL的bigint类型
bigint支持的数字的大小范围为:19位,存电话号码.有符号范围:-9223372036854775808 到 9223372036854775807 int支持的数字范围为:10位,有符号范围:- ...