怎么用短信qq注册不用短信samproxy帐号

[转载]AOP的兑现机制_利用阔乐通信实现PHP网页收发短信_处置定时任务,超时终止方法__脚本百事通
稍等,加载中……
^_^请注意,有可能下面的2篇文章才是您想要的内容:
[转载]AOP的兑现机制
利用阔乐通信实现PHP网页收发短信
处置定时任务,超时终止方法
[转载]AOP的兑现机制
[转载]AOP的实现机制转载自:/blog/1198982
附件中有本文的源代码和Pdf版。本文写的很长的原因,是不希望大家学习AOP时到处找资料,大家有时间可以按照本文动手实践下,相信会有非常大的收获的,有什么问题互相交流,有问必答!
1 AOP各种的实现
AOP就是面向切面编程,我们可以从几个层面来实现AOP。
在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较。
在编译期,切面直接以字节码的形式编译到目标字节码文件中。
对系统无性能影响。
灵活性不够。
在运行期,目标类加载后,为接口动态生成代理类,将切面植入到代理类中。
相对于静态AOP更加灵活。
切入的关注点需要实现接口。对系统有一点性能影响。
动态字节码生成
在运行期,目标类加载后,动态构建字节码文件生成目标类的子类,将切面逻辑加入到子类中。
没有接口也可以织入。
扩展类的实例方法为final时,则无法进行织入。
自定义类加载器
在运行期,目标加载前,将切面逻辑加到目标字节码里。
可以对绝大部分类进行织入。
代码中如果使用了其他类加载器,则这些类将不会被织入。
字节码转换
在运行期,所有类加载器加载字节码前,前进行拦截。
可以对所有类进行织入。
2 AOP里的公民 ?
Joinpoint:拦截点,如某个业务方法。
Pointcut:Joinpoint的表达式,表示拦截哪些方法。一个Pointcut对应多个Joinpoint。
要切入的逻辑。
Before Advice 在方法前切入。
After Advice 在方法后切入,抛出异常时也会切入。
After Returning Advice 在方法返回后切入,抛出异常则不会切入。
After Throwing Advice 在方法抛出异常时切入。
Around Advice 在方法执行前后切入,可以中断或忽略原有流程的执行。 ?
公民之间的关系 织入器通过在切面中定义pointcut来搜索目标(被代理类)的JoinPoint(切入点),然后把要切入的逻辑(Advice)织入到目标对象里,生成代理类。
3 AOP的实现机制
本章节将详细介绍AOP有各种实现机制。
3.1 动态代理
Java在JDK1.3后引入的动态代理机制,使我们可以在运行期动态的创建代理类。使用动态代理实现AOP需要有四个角色:被代理的类,被代理类的接口,织入器,和InvocationHandler,而织入器使用接口反射机制生成一个代理类,然后在这个代理类中织入代码。被代理的类是AOP里所说的目标,InvocationHandler是切面,它包含了Advice和Pointcut。 3.1.1 使用动态代理
那如何使用动态代理来实现AOP。下面的例子演示在方法执行前织入一段记录日志的代码,其中Business是代理类,LogInvocationHandler是记录日志的切面,IBusiness, IBusiness2是代理类的接口,Proxy.newProxyInstance是织入器。 清单一:动态代理的演示
public static void main(String[] args) {
Class[] proxyInterface = new Class[] { IBusiness.class, IBusiness2.class };
LogInvocationHandler handler = new LogInvocationHandler(new Business());
ClassLoader classLoader = DynamicProxyDemo.class.getClassLoader();
IBusiness2 proxyBusiness = (IBusiness2) Proxy.newProxyInstance(classLoader, proxyInterface, handler);
proxyBusiness.doSomeThing2();
((IBusiness) proxyBusiness).doSomeThing();
public static class LogInvocationHandler implements InvocationHandler {
LogInvocationHandler(Object target) {
this.target =
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object rev = method.invoke(target, args);
if (method.getName().equals("doSomeThing2")) {
System.out.println("记录日志");
接口IBusiness和IBusiness2定义省略。
public static void main(String[] args) {
//需要代理的接口,被代理类实现的多个接口都必须在这里定义
Class[] proxyInterface = new Class[] { IBusiness.class, IBusiness2.class };
//构建AOP的Advice,这里需要传入业务类的实例
LogInvocationHandler handler = new LogInvocationHandler(new Business());
//生成代理类的字节码加载器
ClassLoader classLoader = DynamicProxyDemo.class.getClassLoader();
//织入器,织入代码并生成代理类
IBusiness2 proxyBusiness = (IBusiness2) Proxy.newProxyInstance(classLoader, proxyInterface, handler);
//使用代理类的实例来调用方法。
proxyBusiness.doSomeThing2();
((IBusiness) proxyBusiness).doSomeThing();
* 打印日志的切面
public static class LogInvocationHandler implements InvocationHandler {
private O //目标对象
LogInvocationHandler(Object target) {
this.target =
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//执行原有逻辑
Object rev = method.invoke(target, args);
//执行织入的日志,你可以控制哪些方法执行切入逻辑
if (method.getName().equals("doSomeThing2")) {
System.out.println("记录日志");
接口IBusiness和IBusiness2定义省略。
业务类,需要代理的类。
public class Business implements IBusiness, IBusiness2 {
public boolean doSomeThing() {
System.out.println("执行业务逻辑");
return true;
public void doSomeThing2() {
System.out.println("执行业务逻辑2");
public class Business implements IBusiness, IBusiness2 {
public boolean doSomeThing() {
System.out.println("执行业务逻辑");
public void doSomeThing2() {
System.out.println("执行业务逻辑2");
执行业务逻辑2
执行业务逻辑
执行业务逻辑2
执行业务逻辑
可以看到“记录日志”的逻辑切入到Business类的doSomeThing方法前了。
3.1.2 动态代理原理
本节将结合动态代理的源代码讲解其实现原理。动态代理的核心其实就是代理对象的生成,即Proxy.newProxyInstance(classLoader, proxyInterface, handler)。让我们进入newProxyInstance方法观摩下,核心代码其实就三行。 清单二:生成代理类
Class cl = getProxyClass(loader, interfaces);
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
其中getProxyClass(loader, interfaces)方法用于获取代理类,它主要做了三件事情:在当前类加载器的缓存里搜索是否有代理类,没有则生成代理类并缓存在本地JVM里。
清单三:查找代理类
Object key = Arrays.asList(interfaceNames);
synchronized (cache) {
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
if (proxyClass != null) {
return proxyC
} else if (value == pendingGenerationMarker) {
cache.wait();
} catch (InterruptedException e) {
cache.put(key, pendingGenerationMarker);
} while (true);
//获取代理类
Class cl = getProxyClass(loader, interfaces);
//获取带有InvocationHandler参数的构造方法
Constructor cons = cl.getConstructor(constructorParams);
//把handler传入构造方法生成实例
return (Object) cons.newInstance(new Object[] { h });
其中getProxyClass(loader, interfaces)方法用于获取代理类,它主要做了三件事情:在当前类加载器的缓存里搜索是否有代理类,没有则生成代理类并缓存在本地JVM里。
清单三:查找代理类
// 缓存的key使用接口名称生成的List
Object key = Arrays.asList(interfaceNames);
synchronized (cache) {
Object value = cache.get(key);
// 缓存里保存了代理类的引用
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
if (proxyClass != null) {
// 代理类已经存在则返回
return proxyC
} else if (value == pendingGenerationMarker) {
// 如果代理类正在产生,则等待
cache.wait();
} catch (InterruptedException e) {
//没有代理类,则标记代理准备生成
cache.put(key, pendingGenerationMarker);
} while (true);
代理类的生成主要是以下这两行代码。 清单四:生成并加载代理类
proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
//生成代理类的字节码文件并保存到硬盘中,默认不会写入硬盘
proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
//使用类加载器将字节码加载到内存中
proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
ProxyGenerator.generateProxyClass()方法属于sun.misc包下,Oracle并没有提供源代码,但是我们可以使用JD-GUI这样的反编译软件打开jre\lib\rt.jar来一探究竟,以下是其核心代码的分析。 清单五:代理类的生成过程
for (int i = 0; i & this.interfaces. i++) {
localObject1 = this.interfaces[i].getMethods();
for (int k = 0; k & localObject1. k++) {
addProxyMethod(localObject1[k], this.interfaces[i]);
MethodInfo localMethodInfo = new MethodInfo("&init&", "(Ljava/lang/reflect/InvocationH)V", 1);
this.cp.getInterfaceMethodRef("InvocationHandler", "invoke", "O M O")
localFileOutputStream = new FileOutputStream(ProxyGenerator.access$000(this.val$name) + ".class");
localFileOutputStream.write(this.val$classFile);
//添加接口中定义的方法,此时方法体为空
for (int i = 0; i & this.interfaces. i++) {
localObject1 = this.interfaces[i].getMethods();
for (int k = 0; k & localObject1. k++) {
addProxyMethod(localObject1[k], this.interfaces[i]);
//添加一个带有InvocationHandler的构造方法
MethodInfo localMethodInfo = new MethodInfo("&init&", "(Ljava/lang/reflect/InvocationH)V", 1);
//循环生成方法体代码(省略)
//方法体里生成调用InvocationHandler的invoke方法代码。(此处有所省略)
this.cp.getInterfaceMethodRef("InvocationHandler", "invoke", "O M O")
//将生成的字节码,写入硬盘,前面有个if判断,默认不会写入硬盘
localFileOutputStream = new FileOutputStream(ProxyGenerator.access$000(this.val$name) + ".class");
localFileOutputStream.write(this.val$classFile);
那么通过以上分析,我们可以推出动态代理为我们生成了一个这样的代理类。把方法doSomeThing的方法体修改为调用LogInvocationHandler的invoke方法。 清单六:生成的代理类源码
public class ProxyBusiness implements IBusiness, IBusiness2 {
private LogInvocationH
public void doSomeThing2() {
Method m = (h.target).getClass().getMethod("doSomeThing", null);
h.invoke(this, m, null);
} catch (Throwable e) {
public boolean doSomeThing() {
Method m = (h.target).getClass().getMethod("doSomeThing2", null);
return (Boolean) h.invoke(this, m, null);
} catch (Throwable e) {
return false;
public ProxyBusiness(LogInvocationHandler h) {
public static void main(String[] args) {
LogInvocationHandler handler = new LogInvocationHandler(new Business());
new ProxyBusiness(handler).doSomeThing();
new ProxyBusiness(handler).doSomeThing2();
public class ProxyBusiness implements IBusiness, IBusiness2 {
private LogInvocationH
public void doSomeThing2() {
Method m = (h.target).getClass().getMethod("doSomeThing", null);
h.invoke(this, m, null);
} catch (Throwable e) {
// 异常处理(略)
public boolean doSomeThing() {
Method m = (h.target).getClass().getMethod("doSomeThing2", null);
return (Boolean) h.invoke(this, m, null);
} catch (Throwable e) {
// 异常处理(略)
public ProxyBusiness(LogInvocationHandler h) {
public static void main(String[] args) {
//构建AOP的Advice
LogInvocationHandler handler = new LogInvocationHandler(new Business());
new ProxyBusiness(handler).doSomeThing();
new ProxyBusiness(handler).doSomeThing2();
3.1.3 小结
从前两节的分析我们可以看出,动态代理在运行期通过接口动态生成代理类,这为其带来了一定的灵活性,但这个灵活性却带来了两个问题,第一代理类必须实现一个接口,如果没实现接口会抛出一个异常。第二性能影响,因为动态代理使用反射的机制实现的,首先反射肯定比直接调用要慢,经过测试大概每个代理类比静态代理多出10几毫秒的消耗。其次使用反射大量生成类文件可能引起Full GC造成性能影响,因为字节码文件加载后会存放在JVM运行时区的方法区(或者叫持久代)中,当方法区满的时候,会引起Full GC,所以当你大量使用动态代理时,可以将持久代设置大一些,减少Full GC次数。 3.2 动态字节码生成
使用动态字节码生成技术实现AOP原理是在运行期间目标字节码加载后,生成目标类的子类,将切面逻辑加入到子类中,所以使用Cglib实现AOP不需要基于接口。
本节介绍如何使用Cglib来实现动态字节码技术。Cglib是一个强大的,高性能的Code生成类库,它可以在运行期间扩展Java类和实现Java接口,它封装了Asm,所以使用Cglib前需要引入Asm的jar。 清单七:使用CGLib实现AOP
public static void main(String[] args) {
byteCodeGe();
public static void byteCodeGe() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Business.class);
enhancer.setCallback(new LogIntercept());
IBusiness2 newBusiness = (IBusiness2) enhancer.create();
newBusiness.doSomeThing2();
public static class LogIntercept implements MethodInterceptor {
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object rev = proxy.invokeSuper(target, args);
if (method.getName().equals("doSomeThing2")) {
System.out.println("记录日志");
public static void main(String[] args) {
byteCodeGe();
public static void byteCodeGe() {
//创建一个织入器
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(Business.class);
//设置需要织入的逻辑
enhancer.setCallback(new LogIntercept());
//使用织入器创建子类
IBusiness2 newBusiness = (IBusiness2) enhancer.create();
newBusiness.doSomeThing2();
* 记录日志
public static class LogIntercept implements MethodInterceptor {
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//执行原有逻辑,注意这里是invokeSuper
Object rev = proxy.invokeSuper(target, args);
//执行织入的日志
if (method.getName().equals("doSomeThing2")) {
System.out.println("记录日志");
3.3 自定义类加载器
如果我们实现了一个自定义类加载器,在类加载到JVM之前直接修改某些类的方法,并将切入逻辑织入到这个方法里,然后将修改后的字节码文件交给虚拟机运行,那岂不是更直接。
Javassist是一个编辑字节码的框架,可以让你很简单地操作字节码。它可以在运行期定义或修改Class。使用Javassist实现AOP的原理是在字节码加载前直接修改需要切入的方法。这比使用Cglib实现AOP更加高效,并且没太多限制,实现原理如下图:
我们使用系统类加载器启动我们自定义的类加载器,在这个类加载器里加一个类加载监听器,监听器发现目标类被加载时就织入切入逻辑,咱们再看看使用Javassist实现AOP的代码: 清单八:启动自定义的类加载器
ClassPool cp = ClassPool.getDefault();
Loader cl = new Loader();
cl.addTranslator(cp, new MyTranslator());
cl.run("jsvassist.JavassistAopDemo$MyTranslator", args);
//获取存放CtClass的容器ClassPool
ClassPool cp = ClassPool.getDefault();
//创建一个类加载器
Loader cl = new Loader();
//增加一个转换器
cl.addTranslator(cp, new MyTranslator());
//启动MyTranslator的main函数
cl.run("jsvassist.JavassistAopDemo$MyTranslator", args);
清单九:类加载监听器
public static class MyTranslator implements Translator {
public void start(ClassPool pool) throws NotFoundException, CannotCompileException {
public void onLoad(ClassPool pool, String classname) {
if (!"model$Business".equals(classname)) {
cc = pool.get(classname);
CtMethod m = cc.getDeclaredMethod("doSomeThing");
m.insertBefore("{ System.out.println(\"记录日志\"); }");
} catch (NotFoundException e) {
} catch (CannotCompileException e) {
public static void main(String[] args) {
Business b = new Business();
b.doSomeThing2();
b.doSomeThing();
public static class MyTranslator implements Translator {
public void start(ClassPool pool) throws NotFoundException, CannotCompileException {
* 类装载到JVM前进行代码织入
public void onLoad(ClassPool pool, String classname) {
if (!"model$Business".equals(classname)) {
//通过获取类文件
cc = pool.get(classname);
//获得指定方法名的方法
CtMethod m = cc.getDeclaredMethod("doSomeThing");
//在方法执行前插入代码
m.insertBefore("{ System.out.println(\"记录日志\"); }");
} catch (NotFoundException e) {
} catch (CannotCompileException e) {
public static void main(String[] args) {
Business b = new Business();
b.doSomeThing2();
b.doSomeThing();
执行业务逻辑2
执行业务逻辑
执行业务逻辑2
执行业务逻辑
其中Bussiness类在本文的清单一中定义。看起来是不是特别简单,CtClass是一个class文件的抽象描述。咱们也可以使用insertAfter()在方法的末尾插入代码,使用insertAt()在指定行插入代码。 3.3.1 小结
从本节中可知,使用自定义的类加载器实现AOP在性能上要优于动态代理和Cglib,因为它不会产生新类,但是它仍然存在一个问题,就是如果其他的类加载器来加载类的话,这些类将不会被拦截。 3.4 字节码转换
自定义的类加载器实现AOP只能拦截自己加载的字节码,那么有没有一种方式能够监控所有类加载器加载字节码呢?有,使用Instrumentation,它是 Java 5 提供的新特性,使用 Instrumentation,开发者可以构建一个字节码转换器,在字节码加载前进行转换。本节使用Instrumentation和javassist来实现AOP。 3.4.1 构建字节码转换器
首先需要创建字节码转换器,该转换器负责拦截Business类,并在Business类的doSomeThing方法前使用javassist加入记录日志的代码。
public class MyClassFileTransformer implements ClassFileTransformer {
public byte[] transform(ClassLoader loader, String className, Class&?& classBeingRedefined,
ProtectionDomain protectionDomain, <span style="color: #7f005
利用阔乐通信实现PHP网页收发短信
利用宽乐通信实现PHP网页收发短信一直想为网站提供收发短信的功能。
最近学习了一下宽乐通信,
它是电信提供的一个服务,是华为公司开发的,以WebService方式提供了收发短信的开发接口, 用PHP调用这个接口就可以收发短信了。
使用宽乐通信前,要先开通一个帐号、密码(在电信公司开通,帐号即电话号码,开通时要声明是WebService方式的,否则不能用)
发短信是需要收费的,每条8分,接收免费。
宽乐通信有一个接口文档,用于二次开发的。在百度搜索 ”宽乐通信接口“ 即可找到
宽乐通信提供两种接口:
一种是SDK方式,即以Windows COM组件方式提供,用于编写Windows客户端程序
另一种是WebService方式,可用于网站开发。
所谓WebService,就是Web服务,是一种网络函数,可以看作另一个网站给你提供的函数,是一个网站调用另一个网站的功能的一种标准接口,具体来说,如果要调用其它网站的功能,向指定的URL发出一个POST请求,请求内容中包含的函数名和参数(XML格式), 响应结果中是函数返回值。
要详细了解WebService的数据格式, 具体看相关文档。
PHP5中提供了两个类
SoapClient (客户端, 使用WebService)和 SoapServer(服务器,提供WebService),可以很容易地调用WebService.
宽乐通信接口文档很长,简单讲一下收发短信的原理:
宽乐通信提供了一系列接口,其中与短信相关的有: Register, SendSMS两个接口
发短信的过程:
1, 首先通过WebService方式调用
Register 接口中的 函数
getRandom(), 取得宽乐通信平台下发的一个随机数rand
2, 然后调用 Register 接口中的 setCallBackAddr()函数实现登录
函数原型:String setCallBackAddr(String uc, String pw, String rand, String url);
参数: uc 是帐号
pw 是getRandom获取的随机数 rand+UC密码+UC密码 经过MD5加密后的字符串 (就是把rand与密码字符串两次相连后,进行MD5加密)
rand 是getRandom获取的随机数
url 是回调函数的url (这个回调函数是在接收短信时用到的,在这个URL上你要先实现一个WebService, 当你的宽乐通信帐号收到短信,宽乐通信平台将会调用你的WebService)
返回值是一个连接ID (connID), 这个ID用于后续发短信
3,然后,就可以通过调用 SendSMS 接口中的 sendSMS()函数发送短信了
函数原型:String sendSMS(String uc, String pw, String rand, String callee[], String isreturn, String cont, int msgid, String connID);
参数: uc 是帐号
pw 是getRandom获取的随机数 rand+UC密码+UC密码 经过MD5加密后的字符串 (就是把rand与密码字符串两次相连后,进行MD5加密)
rand 是getRandom获取的随机数
callee 是接收短信的号码,是一个字符串数组,可以放多个号码
isreturn 是否需要短信回执,这是宽乐通信很强的一个功能,当接收方已接收到短信,则宽乐通信平台会发送一个回执给短信发送方
是短信内容,中文必须是gbk编码, 还要再进行base64编码
msgid 是短信的唯一编号, 你自己编的,收到短信回执中有这个msgid编号,这样就可以知道是哪条短信被接收了
connID 就是setCallBackAddr()函数返回的连接ID
收短信的过程:
调用 setCallBackAddr() 函数时要提供一个回调函数的url , 把这个URL指向你的网站,在这个URL上你要先实现一个WebService, 提供三个函数:echoOfSendSMS(), recvSMS(), NotifyStatus().
当收到短信时,宽乐通信平台会调用你指定的URL中的recvSMS()函数
当收到短信回执时,宽乐通信平台会调用你指定的URL中的echoOfSendSMS()函数
当状态变化时,宽乐通信平台会调用你指定的URL中的NotifyStatus()函数
你在自已的网站通过编写这三个webservice函数, 就可以实现接收短信了。
函数原型:String recvSMS(String caller, String time, String cont, String ucNum);
参数: caller是发送短信的号码,cont是短信内容(需要base64解码),
ucNum是短信接受者号码
函数原型:void echoOfSendSMS(String ucNum, String cee, int msgid, int res, String recvt);
函数原型:void NotifyStatus(int eventID, String sessionID,int res,String para1);
原理讲完了,看一下PHP代码的实现:
开发语言:PHP 5.X
发送短信的代码如下:
$uc="02087XXXX1";
//宽乐通信帐号
$pass="uu1XXXX56";
//宽乐通信密码
$callBackURL='/receive_sms.php'; //回调URL,如果不想接收短信,则这个URL可以随便写
$urlRegister="http://202.105.212.146:8080/jboss-net/services/Register?wsdl"; //Register接口URL
$client = new SoapClient($urlRegister); //生成一个SoapClient对象, 使用Register接口
$rand = $client-&__call("getRandom", array()); //调用getRandom()函数,取得随机数
$pw = md5($rand.$pass.$pass); //计算PW值,
$connID = $client-&__call("setCallBackAddr", array($uc,$pw,$rand,$callBackURL));//调用setCallBackAddr()函数,取得连接ID
if ($connID&0) {
//如果connID&0, 则表示登录失败, connID是错误码
print "error login";
$urlSendSms="http://202.105.212.146:8080/jboss-net/services/SendSMS?wsdl";//SendSMS接口URL
$client1 = new SoapClient($urlSendSms);//生成一个SoapClient对象, 使用SendSMS接口
$callee = array(""); //接收短信的号码,做为一个数组
$content = "hello,sms from php"; //短信内容
$content = base64_encode($content); //将短信内容进行base64编码
$msgId = 1; //短信编号,可以随便编号
$needReceipt = '0'; //是否需要回执, 字符串型,'0'表示不要回执,'1'表示要回执
//调用SendSMS接口中的 sendSMS函数,发送短信
$result = $client1-&__call("sendSMS", array($uc,$pw,$rand,$callee,$needReceipt,$content,$msgId,$connID));
if ($result==0) {
//如果返回值为0,则发送成功
print "send OK";
print "send error, error code=".$ //否则,返回值即是错误码
程序注释已经很清晰了,补充说明:上述程序中的帐号、密码要更改为你的实际帐号密码
下面是,接收短信的php代码, 文件: receive_sms.php
* 接收短信回执
* 函数原型:void echoOfSendSMS(String ucNum, String cee, int msgid, int res, String recvt);
* @param string $ucNum 发送方号码
* @param string $cee 接收方号码
* @param int $msgid 短消息编号,用于客户端匹配请求消息
* @param int $res 回执的结果(=1表示接收方成功接收短信, -1为系统异常;-12:系统超时;-92:短信无法送达对方)
* @param string $recvt 短消息时间
* @return 无返回值
function echoOfSendSMS($ucNum,$cee,$msgid,$res,$recvt){
$filename = "echo.txt";
$data = "ucNum=".$ucNum." cee=".$cee." msgid=".$msgid." res=".$res." recvt=".$recvt."\r\n";
file_put_contents($filename, $data, FILE_APPEND);
* 接收短信
* 函数原型:String recvSMS(String caller, String time, String cont, String ucNum);
* @param string $caller 短信的发送者号码
* @param string $time 短信发送时间
* @param string $cont 短信内容(需要对短信内容进行BASE64解码)
* @param string $ucNum 短信接受者号码(接收短信的UC号码)
* @return string =0:成功返回,
&0:失败码
function recvSMS($caller, $time, $cont, $ucNum) {
$filename = "sms.txt";
$data = "caller:".$caller." time=".$time." ucNum=".$ucNum." content=".base64_decode($cont)."\r\n";
file_put_contents($filename, $data, FILE_APPEND);
return "0";
* 通用回调函数: 通知状态变化
* 函数原型:void NotifyStatus(int eventID, String sessionID,int res,String para1);
* @param integer $eventId 接口事件ID
* @param string $sessionId 呼叫标识/会议标识/短信标识/传真标识:
* @param int $res 失败码/状态码
* @param string $para1 参数1
* @return 无返回值
function NotifyStatus($eventId, $sessionId, $res, $para1) {
$filename = "notify.txt";
$data = "eventId:".$eventId." sessionId=".$sessionId." res=".$res." para1=".$para1."\r\n";
file_put_contents($filename, $data, FILE_APPEND);
//主程序开始
//初始化WebService服务
$server = new SoapServer(null,array('uri'=&"/receive_sms.php"));//这个uri要写本php文件所在的uri
//注册三个函数
$server-&addFunction(array("echoOfSendSMS","recvSMS","NotifyStatus"));
//启动soap server
$server-&handle();
程序注释很清晰,就是定义三个函数,生成一个WebService服务程序中接收到短信后,只是存盘。你可以修改recvSMS()函数,增加自己想要的功能,比如:写数据库、回复短信等
为简化发送短信的过程,我编写了一个Sms类,对发短信过程进行了封装,使用者不需要懂宽乐通信接口,只要有宽乐通信帐号密码,发送短信只需要三句,例如:
$sms = new Sms(); //产生一个Sms类的对象
if ($sms-&login($account, $password))
$sms-&send("139876XXXXX", "hello,sms"); //发短信
够简单了吧。
Sms类的源码文件 class.Sms.php 及接收短信的源码 receive_sms.php 可以在我的资源中下载,分享给大家
网站能收发短信后,就可以实现很多功能,比如:发送验证码、有人登录网站时可以发短信通知到你的手机、发短信就可以触发网站运行。
网站因此就活动起来了!!!
处置定时任务,超时终止方法
处理定时任务,超时终止方法
实现功能:处理一批任务,如果某个任务的处理时间超过最大处理时间,则终止该任务的执行,继续执行下一个任务实现思路:三线程实现,处理一个任务时,启动一个任务处理线程处理方案,再启动一个定时器线程检测是否超时,并通过一个同步变量保证任务时串行执行的。实现代码如下:疑问:1、在Java中,类似超时任务的处理有没有其它的实现方式?2、下面几个异常会无规律地出现,想不明白其中的道理,请明白人帮忙解释一下,2.1、没有执行“Normal Process”,也没有执行“ending ok!” :为什么interrupt后,doSomething里没有捕获到异常? start task!20ThreadID:27&&& starting!ThreadID: MonitorThread running!ThreadID:27&&& stoping end!end task!202.2、没有执行“ending ok!” :stop后,run里后续处理不做了? start task!18ThreadID:25&&& starting!ThreadID: MonitorThread running!ThreadID:25&&& AbNormal Proccess! processTime=18000ThreadID:25&&& stoping end! 2.3、执行了2次“AbNormal Proccess! ”,但没有执行“ending ok!” :为什么会打印2次?start task!10ThreadID:17&&& starting!ThreadID: MonitorThread running!ThreadID:17&&& AbNormal Proccess! processTime=10000ThreadID:17&&& AbNormal Proccess! processTime=10000ThreadID:17&&& stoping end!end task!10代码如下:Java codepackage MultiThreadTimport java.util.Timport java.util.TimerTpublic class MainThread {
private Object lock = new Object();
public void waitLock() throws InterruptedException {
synchronized (lock) {
lock.wait();
public void notifyLock() {
synchronized (lock) {
lock.notify();
* @param args
* @throws InterruptedException
public static void main(String[] args) {
MainThread mainThread = new MainThread();
for (int i = 2; i &= 20; i += 2) {
System.out.println("start task!" + i);
ProccessThread proccessThread = new ProccessThread(mainThread,
i * 1000);
MonitorThread monitorThread = new MonitorThread(mainThread);
long maxProccessTime = 8 * 1000;// 每个任务的最大处理时间
Timer timer = new Timer();
timer.schedule(monitorThread, maxProccessTime);
proccessThread.start();
mainThread.waitLock();
} catch (InterruptedException e) {
e.printStackTrace();
proccessThread.stop();
timer.cancel();
System.out.println("end task!" + i);
}}class MonitorThread extends TimerTask {
private MainT
public MonitorThread(MainThread mt) {
public void run() {
System.out.println("ThreadID:" + " MonitorThread running!");
mt.notifyLock();
}}class ProccessThread implements Runnable {
private MainT
private long processT
public ProccessThread(MainThread mt, long processTime) {
this.processTime = processT
private void doSomething() {
// do something
// thread.sleep(100*1000); //异常情况
// thread.sleep(1*1000); //正常情况
thread.sleep(processTime); // 正常情况
System.out.println("ThreadID:" + thread.getId() + "&&&
Normal Process! processTime=" + processTime);
} catch (InterruptedException e) {
// e.printStackTrace();
System.out.println("ThreadID:" + thread.getId() + "&&&
AbNormal Proccess! processTime=" + processTime);
public void run() {
System.out.println("ThreadID:" + thread.getId() + "&&& starting!");
doSomething();
mt.notifyLock();
System.out.println("ThreadID:" + thread.getId() + "&&& ending ok!");
public void start() {
thread = new Thread(this);
thread.start();
public void stop() {
thread.interrupt();// 如果任务在正常时间内不能退出,认为产生interrupt,强行地退出 (run方法正常结束)
thread.stop();
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("ThreadID:" + thread.getId()
+ "&&& stoping end!");
如果您想提高自己的技术水平,欢迎加入本站官方1号QQ群:&&,&&2号QQ群:,在群里结识技术精英和交流技术^_^
本站联系邮箱:

我要回帖

更多关于 不用短信验证注册qq 的文章

 

随机推荐