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的更多相关文章

  1. 利用shell脚本将Oracle服务器中数据定时增量刷新到ftp服务器中

    现有需求:将oracle数据库中的数据准实时同步至某ftp服务器中,以便前端应用能定时从ftp服务器目录中取增量数据 方法:将加工脚本写为存储过程,然后利用shell脚本执行该存储过程并将增量数据导出 ...

  2. 利用shell脚本实现计划任务功能 V1.2

    2013.05.10  mytask 1.2 主程序休眠时间分成若干小的时间片断分段休眠,避免长时间的休眠不能及时响应系统信号. 2013.05.07 mytask 1.1 昨天发布了mytask1. ...

  3. 利用shell脚本或者php移动某个文件夹下的文件到各自的日期组成的目录下

    背景是这样的:网站一开始访问量比较小,大家就把所有的图片文件上传到一个目录下(比如是/data/images/).后来访问量大了,图片也多了,这样就影响读取效率.所以有个这样的需求,把这些个图片文件移 ...

  4. 利用shell脚本个性化运行jar任务

    利用shell脚本可以个性化运行jar任务,废话不多说,直接上代码: #!/bin/bash APP_PATH=/root/bigdata/jars/data_migration_from_sqlse ...

  5. 利用shell脚本去备份幸运28源码搭建下载所指定的数据库

    #! /bin/bash幸运28源码搭建下载Q[115288oo99]logintool=/home/yx/server/mysql/mysql/bin/mysqldumptool=/home/yx/ ...

  6. (第二篇)shell的简单了解

    Shell (类似开发工具) Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程 ...

  7. windows下建立文件的换行符^M导致linux下的shell脚本执行错误的解决方式

    常常在windows下编辑的文件远程传送到linux下的时候每行末尾都会出现^M.这将导致shell脚本执行错误,主要是由于dos下的编辑器和linux下的编辑器对文件末行的回车符处理不一致导致. 主 ...

  8. 远程shell脚本执行工具类

    /** * 远程shell脚本执行工具类 */public class RemoteShellExecutorUtils { private static final Logger logger = ...

  9. shell脚本执行错误 $'\r':command not found

    shell脚本执行错误 $'\r':command not found Linux下有命令dos2unix 可以用一下命令测试 vi -b filename 我们只要输入dos2unix *.sh就可 ...

随机推荐

  1. Codeforces Round #466 (Div. 2) 题解

    人生中第三次\(CF\)... 考试中切了\(A\)~\(E\) \(F\)题会做没时间写 题解 A:Points on the line 题意 给定一个数列,删最小的数,使最大差不大于一个定值 So ...

  2. golang []byte转string

    golang中,字符切片[]byte转换成string最简单的方式是 package main import ( "fmt" _ "unsafe" ) func ...

  3. VS快速注释

    注释:Ctrl+k  + Ctrl+c 去注释:Ctrl+k + Ctrl +u

  4. grub4dos和winsetupfromusb1.4

    其实grub4dos也是一个多系统启动盘制作软件,GRUB4DOS 最大的成功之处就是既学习了windows的方便易用,又引入linux的强大功能.http://baike.baidu.com/lin ...

  5. Windows 8 系统快捷键热键列表收集

    值得收藏参考的 Windows 8 系统快捷键热键列表收集大全汇总,键盘党效率党必备啊! 相信不少喜欢接触新鲜软件的同学都已经给电脑安装上Windows 8 操作系统了吧!这个系统优秀与否我们暂且不讨 ...

  6. python全栈开发-Day3 字符串

    python全栈开发-Day3 字符串 一.按照以下几个点展开字符串的学习  #一:基本使用 1. 用途 #首先字符串主要作用途径:名字,性别,国籍,地址等描述信息2.定义方式 在单引号\双引号\三引 ...

  7. 用于 SELECT 和 WHERE 子句的函数

    一个 SQL 语句中的 select_expression 或 where_definition 可由任何使用了下面所描述函数的表达式组成. 包含 NULL 的表达式总是得出一个 NULL 值结果,除 ...

  8. nginx location匹配顺序及CI框架的nginx配置

    Nginx location匹配顺序如下: 用前缀字符串定义的location规则对URI进行匹配测试. =号定义了精确的前缀字符串匹配,如果发现精确匹配则使用当前规则.否则继续下一步匹配. 匹配其它 ...

  9. Knowledge point

    静态网页的特点:以htm.html.sbtml.xml.js.css等为后缀扩展名. 1)程序在客户浏览器端解析,不需要读取数据库,性能和效率较高: 2)后端没有数据库支持,所以和用户的交互性差,功能 ...

  10. 分别用EasyAR和Vuforia开发AR(入门级)

    最近在一边学习谷歌TensorFlow,一边在做些简单的AR demo,在此总结下学习经验(自学的过程异常痛苦啊,还有总会有好人会在社区分享经验,这就是前人栽树,后人乘凉呐) 自从任天堂推出<精 ...