Java实现CORBA静态绑定(六)

本文主要内容涉及:

  • CORBA基本架构
  • IDL文件编写
  • POA示例实现
  • POA+TIE示例实现
  • ImplBase示例实现
  • ImplBase+TIE示例实现
  • Persistent示例实现

ImplBase主要是为了兼容旧代码所提供的,正常情况下,大家是不需要使用的。
JDK提供了工具,可以直接生成stubs及skeletons接口代码:

idlj -fall -oldImplBase Hi.idl
idlj -fallTie -oldImplBase Hi.idl

编写server端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.util.Properties;

class HiImpl extends _HiImplBase{
	private ORB orb;
	public void setORB(ORB orb_val){
		orb = orb_val;
	}
	// implement sayHiTo() method
	public String sayHiTo(String someone) {
		return "\nHi, "+someone+" !"+"\n";
	}
	// implement add() method
	public int add(int numa, int numb) {
		return numa+numb;
	}
	// implement shutdown() method
	public void shutdown() {
		orb.shutdown(false);
	}
}

public class HiServer {
	public static void main(String args[]) {
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// create servant and register it with the ORB
			HiImpl hiImpl = new HiImpl();
			hiImpl.setORB(orb);
			// create a tie, with servant being the delegate.
			Hi_Tie tie = new Hi_Tie(hiImpl);
			// obtain the objectRef for the tie
			// this step also implicitly activates the object
			Hi href =  HiHelper.narrow(tie);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			NamingContext ncRef = NamingContextHelper.narrow(objRef);
			// bind the Object Reference in Naming
			NameComponent nc = new NameComponent("Hi", "");
			NameComponent path[] = {nc};
			ncRef.rebind(path, href);
			System.out.println("HiServer ready and waiting ...");
			// wait for invocations from clients
			orb.run();
		}
		catch (Exception e) {
			System.err.println("ERROR: " + e);
			e.printStackTrace(System.out);
		}
		System.out.println("HiServer Exiting ...");
	}
}

编写client端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

public class HiClient{
	public static void main(String args[]){
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			NamingContext ncRef = NamingContextHelper.narrow(objRef);
			// resolve the Object Reference in Naming
			NameComponent nc = new NameComponent("Hi", "");
			NameComponent path[] = {nc};
			Hi hiImpl = HiHelper.narrow(ncRef.resolve(path));
			System.out.println("Obtained a handle on server object: " + hiImpl);
			System.out.println(hiImpl.sayHiTo("neohope"));
			System.out.println(hiImpl.add(70, 80));
			hiImpl.shutdown();
		}
		catch (Exception e) {
			System.out.println("ERROR : " + e) ;
			e.printStackTrace(System.out);
		}
	}
}

编译代码:

javac *.java HiCorba/*.java

测试,在三个shell或cmd窗口中依次运行:

#shell01
orbd -ORBInitialPort 1900
#shell02
java HiServer -ORBInitialPort 1900
>>HiServer ready and waiting ...
>>HiServer Exiting ...
#shell03
java HiClient -ORBInitialPort 1900 -ORBInitialHost localhost
>>Obtained a handle on server object: IOR:000000000000001349444c3a4869436f7262612f
  48693a312e30000000000001000000000000006e000102000000000d3139322e3136382e35362e31
  00007dfd00000019afabcb000000000276c739500000000800000001000000001400000000000002
  00000001000000200000000000010001000000020501000100010020000101090000000100010100
  00000026000000020002
>>Hi, neohope !
>>150

Java实现CORBA静态绑定(五)

本文主要内容涉及:

  • CORBA基本架构
  • IDL文件编写
  • POA示例实现
  • POA+TIE示例实现
  • ImplBase示例实现
  • ImplBase+TIE示例实现
  • Persistent示例实现

ImplBase主要是为了兼容旧代码所提供的,正常情况下,大家是不需要使用的。
JDK提供了工具,可以直接生成stubs及skeletons接口代码:

idlj -fall -oldImplBase Hi.idl

编写server端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.util.Properties;

class HiImpl extends _HiImplBase{
	private ORB orb;
	public void setORB(ORB orb_val){
		orb = orb_val;
	}
	// implement sayHiTo() method
	public String sayHiTo(String someone) {
		return "\nHi, "+someone+" !"+"\n";
	}
	// implement add() method
	public int add(int numa, int numb) {
		return numa+numb;
	}
	// implement shutdown() method
	public void shutdown() {
		orb.shutdown(false);
	}
}

public class HiServer {
	public static void main(String args[]) {
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// create servant and register it with the ORB
			HiImpl hiImpl = new HiImpl();
			hiImpl.setORB(orb);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			NamingContext ncRef = NamingContextHelper.narrow(objRef);
			Hi href = HiHelper.narrow(hiImpl);
			// bind the Object Reference in Naming
			NameComponent nc = new NameComponent("Hi", "");
			NameComponent path[] = {nc};
			ncRef.rebind(path, href);
			System.out.println("HiServer ready and waiting ...");
			// wait for invocations from clients
			orb.run();
		}
		catch (Exception e) {
			System.err.println("ERROR: " + e);
			e.printStackTrace(System.out);
		}
		System.out.println("HiServer Exiting ...");
	}
}

编写client端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

public class HiClient{
	public static void main(String args[]){
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			NamingContext ncRef = NamingContextHelper.narrow(objRef);
			// resolve the Object Reference in Naming
			NameComponent nc = new NameComponent("Hi", "");
			NameComponent path[] = {nc};
			Hi hiImpl = HiHelper.narrow(ncRef.resolve(path));
			System.out.println("Obtained a handle on server object: " + hiImpl);
			System.out.println(hiImpl.sayHiTo("neohope"));
			System.out.println(hiImpl.add(70, 80));
			hiImpl.shutdown();
		}
		catch (Exception e) {
			System.out.println("ERROR : " + e) ;
			e.printStackTrace(System.out);
		}
	}
}

编译代码:

javac *.java HiCorba/*.java

测试,在三个shell或cmd窗口中依次运行:

#shell01
orbd -ORBInitialPort 1900
#shell02
java HiServer -ORBInitialPort 1900
>>HiServer ready and waiting ...
>>HiServer Exiting ...
#shell03
java HiClient -ORBInitialPort 1900 -ORBInitialHost localhost
>>Obtained a handle on server object: IOR:000000000000001349444c3a4869436f7262612f
  48693a312e30000000000001000000000000006e000102000000000d3139322e3136382e35362e31
  000074c300000019afabcb0000000002768712000000000800000001000000001400000000000002
  00000001000000200000000000010001000000020501000100010020000101090000000100010100
  00000026000000020002
>>Hi, neohope !
>>150

Java实现CORBA静态绑定(四)

本文主要内容涉及:

  • CORBA基本架构
  • IDL文件编写
  • POA示例实现
  • POA+TIE示例实现
  • ImplBase示例实现
  • ImplBase+TIE示例实现
  • Persistent示例实现

与POA方式相比,POA-Tie将继承方式,调整为委托方式,降低了软件的耦合度。

JDK提供了工具,可以直接生成stubs及skeletons接口代码:

idlj -fall Hi.idl
idlj -fallTie Hi.idl

编写server端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;
import java.util.Properties;

class HiImpl extends HiPOA {
	private ORB orb;
	public void setORB(ORB orb_val) {
		orb = orb_val;
	}
	// implement sayHiTo() method
	public String sayHiTo(String someone) {
		return "\nHi, "+someone+" !"+"\n";
	}
	// implement add() method
	public int add(int numa, int numb) {
		return numa+numb;
	}
	// implement shutdown() method
	public void shutdown() {
		orb.shutdown(false);
	}
}

public class HiServer{
	public static void main(String args[]){
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// Get reference to rootpoa & activate the POAManager
			POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
			rootpoa.the_POAManager().activate();
			// create servant and register it with the ORB
			HiImpl hiImpl = new HiImpl();
			hiImpl.setORB(orb);
			// create a tie, with servant being the delegate.
			HiPOATie tie = new HiPOATie(hiImpl, rootpoa);
			// obtain the objectRef for the tie
			// this step also implicitly activates the object
			Hi href = tie._this(orb);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			// Use NamingContextExt which is part of the Interoperable
			// Naming Service specification.
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
			// bind the Object Reference in Naming
			String name = "Hi";
			NameComponent path[] = ncRef.to_name( name );
			ncRef.rebind(path, href);
			System.out.println("HiServer ready and waiting ...");
			// wait for invocations from clients
			orb.run();
		}
		catch (Exception e){
			System.err.println("ERROR: " + e);
			e.printStackTrace(System.out);
		}
		System.out.println("HiServer Exiting ...");
	}
}

编写client端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

public class HiClient{
	public static void main(String args[]){
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			// Use NamingContextExt instead of NamingContext. This is
			// part of the Interoperable naming Service.
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
			// resolve the Object Reference in Naming
			String name = "Hi";
			Hi hiImpl = HiHelper.narrow(ncRef.resolve_str(name));
			System.out.println("Obtained a handle on server object: " + hiImpl);
			System.out.println(hiImpl.sayHiTo("neohope"));
			System.out.println(hiImpl.add(70, 80));
			hiImpl.shutdown();
		}
		catch (Exception e) {
			System.out.println("ERROR : " + e) ;
			e.printStackTrace(System.out);
		}
	}
}

编译代码:

javac *.java HiCorba/*.java

测试,在三个shell或cmd窗口中依次运行:

#shell01
orbd -ORBInitialPort 1900
#shell02
java HiServer -ORBInitialPort 1900
>>HiServer ready and waiting ...
>>HiServer Exiting ...
#shell03
java HiClient -ORBInitialPort 1900 -ORBInitialHost localhost
>>Obtained a handle on server object: IOR:000000000000001349444c3a4869436f7262612f
  48693a312e300000000000010000000000000086000102000000000d3139322e3136382e35362e31
  0000744700000031afabcb00000000207673791300000001000000000000000100000008526f6f74
  504f4100000000080000000100000000140000000000000200000001000000200000000000010001
  00000002050100010001002000010109000000010001010000000026000000020002
>>Hi, neohope !
>>150

Java实现CORBA静态绑定(三)

本文主要内容涉及:

  • CORBA基本架构
  • IDL文件编写
  • POA示例实现
  • POA+TIE示例实现
  • ImplBase示例实现
  • ImplBase+TIE示例实现
  • Persistent示例实现

POA(Portable Object Adapter)提供了一组服务器端的接口以及操作,包括:跟踪侍服对象的实例化以及内存空间信息、服务对象的激活以及反激活、对象引用的创建、对象生命周期的管理等。

JDK提供了工具,可以直接生成stubs及skeletons接口代码:

idlj -fall Hi.idl

编写server端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;
import java.util.Properties;

class HiImpl extends HiPOA {
	private ORB orb;
	public void setORB(ORB orb_val) {
		orb = orb_val;
	}
	// implement sayHiTo() method
	public String sayHiTo(String someone) {
		return "\nHi, "+someone+" !"+"\n";
	}
	// implement add() method
	public int add(int numa, int numb) {
		return numa+numb;
	}
	// implement shutdown() method
	public void shutdown() {
		orb.shutdown(false);
	}
}

public class HiServer {
	public static void main(String args[]) {
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// get reference to rootpoa & activate the POAManager
			POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
			rootpoa.the_POAManager().activate();
			// create servant and register it with the ORB
			HiImpl hiImpl = new HiImpl();
			hiImpl.setORB(orb);
			// get object reference from the servant
			org.omg.CORBA.Object ref = rootpoa.servant_to_reference(hiImpl);
			Hi href = HiHelper.narrow(ref);
			// get the root naming context
			// NameService invokes the name service
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			// Use NamingContextExt which is part of the Interoperable
			// Naming Service (INS) specification.
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
			// bind the Object Reference in Naming
			String name = "Hi";
			NameComponent path[] = ncRef.to_name( name );
			ncRef.rebind(path, href);
			System.out.println("HiServer ready and waiting ...");
			// wait for invocations from clients
			orb.run();
		}
		catch (Exception e) {
			System.err.println("ERROR: " + e);
			e.printStackTrace(System.out);
		}
		System.out.println("HiServer Exiting ...");
	}
}

编写client端代码:

import HiCorba.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

public class HiClient
{
	static Hi hiImpl;
	public static void main(String args[])
	{
		try{
			// create and initialize the ORB
			ORB orb = ORB.init(args, null);
			// get the root naming context
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			// Use NamingContextExt instead of NamingContext. This is
			// part of the Interoperable naming Service.
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
			// resolve the Object Reference in Naming
			String name = "Hi";
			hiImpl = HiHelper.narrow(ncRef.resolve_str(name));
			System.out.println("Obtained a handle on server object: " + hiImpl);
			System.out.println(hiImpl.sayHiTo("neohope"));
			System.out.println(hiImpl.add(70, 80));
			hiImpl.shutdown();
		} catch (Exception e) {
			System.out.println("ERROR : " + e) ;
			e.printStackTrace(System.out);
		}
	}
}

编译代码:

javac *.java HiCorba/*.java

测试,在三个shell或cmd窗口中依次运行:

#shell01
orbd -ORBInitialPort 1900
#shell02
java HiServer -ORBInitialPort 1900
>>HiServer ready and waiting ...
>>HiServer Exiting ...
#shell03
java HiClient -ORBInitialPort 1900 -ORBInitialHost localhost
>>Obtained a handle on server object: IOR:000000000000001349444c3a4869436f7262612f
  48693a312e300000000000010000000000000086000102000000000d3139322e3136382e35362e31
  0000732000000031afabcb000000002076625c7400000001000000000000000100000008526f6f74
  504f4100000000080000000100000000140000000000000200000001000000200000000000010001
  00000002050100010001002000010109000000010001010000000026000000020002
>>Hi, neohope !
>>150

Java实现CORBA静态绑定(二)

本文主要内容涉及:

  • CORBA基本架构
  • IDL文件编写
  • POA示例实现
  • POA+TIE示例实现
  • ImplBase示例实现
  • ImplBase+TIE示例实现
  • Persistent示例实现

要写一个静态绑定的CORBA程序,首先要完成的就是定义接口。CORBA采用的接口描述方式为IDL(Interface Description Language),IDL的语法规则类似于CPP,所以Java的类型需要做类型映射。常见类型映射关系如下:

IDL Type Java Type
module package
boolean boolean
char, wchar char
octet byte
string, wstring java.lang.String
short, unsigned short short
long, unsigned long int
long long, unsigned long long long
float float
double double
fixed java.math.BigDecimal
enum, struct, union class
sequence, array array
interface (non-abstract) signature interface and an operations interface, helper class, holder class
interface (abstract) signature interface, helper class, holder class
constant (not within an interface) public interface
constant (within an interface) fields in the Java signature interface for non-abstract, or the sole Java interface for abstract
exception class
Any org.omg.CORBA.Any
type declarations nested within interfaces “scoped” package
typedef helper classes
pseudo objects pseudo interface
readonly attribute accessor method
readwrite attribute accessor and modifer methods
operation method

现在,写一个很简单的IDL文件:
hi.idl

module HiCorba
{
	interface Hi
	{
		string sayHiTo(in string someone);
		long add(in long numa, in long numb);
		oneway void shutdown();
	};
};

Java实现CORBA静态绑定(一)

本文主要内容涉及:

  • CORBA基本架构
  • IDL文件编写
  • POA示例实现
  • POA+TIE示例实现
  • ImplBase示例实现
  • ImplBase+TIE示例实现
  • Persistent示例实现

CORBA(Common Object Request Broker Architecture),即公用对象请求代理程序体系结构,是一种为解决分布式处理环境中硬件和软件系统的互连而提出的一种解决方案。其基本架构如下:

Object Services,即对象服务,是为使用和实现对象而提供的基本对象集合,这些服务应独立于应用领域。主要的CORBA服务有:名录服务(Naming Service)、事件服务(Event Service)、生命周期服务(Life Cycle Service)、关系服务(Relationship Service)以及事务服务(Transaction Service)等。这些服务几乎包括分布系统和面向对象系统的各个方面,每个组成部分都非常复杂。

IDL(Interface Description Language),即接口定义语言,是用来描述软件组件接口的一种规范语言。用户可以定义模块、接口、属性、方法、输入输出参数,甚至异常等等。IDL在不同的语言下都有相应的实现,可以把IDL描述的接口编译为目标语言,包括客户端代理和服务器端框架,以及相应的帮助类等等。比如Java中提供过了idlj命令用来编译。

ORB(Object Request Broker),即对象请求代理,是一个中间件,在对象间建立客户-服务器的关系。通过 ORB,一个客户可以很简单地使用服务器对象的方法而不论服务器是在同一机器上还是通过一个网络访问。ORB 截获调用然后负责找到一个对象实现这个请求,传递参数和方法,最后返回结果。客户不用知道对象在哪里,是什么语言实现的,他的操作系统以及其他和对象接口无关的东西。

CORBA按接口绑定方式,分为两大类,一类为动态绑定,一类为静态绑定。这里主要讲的是静态绑定。
在静态绑定时,客户端需要实现IDL Stubs,服务端需要实现IDL Skeleton。
在静态绑定中,CORBA在服务端实现IDL接口有两种方式,一种为继承模式(分为标准模式POA及兼容模式ImplBase),另一种为为委托模式(分为标准模式POA/Tie及兼容模式ImplBase/Tie)。各模式的区别主要在于生成IDL代码时,输入的参数不同,从而生成的接口不同,实现方式也略有区别。这里主要讲的为标准模式。

一次典型的CORBA调用,流程如下图所示:

GIOP(General Inter-ORB Protocol),即通用对象请求代理间通信协,提供了一个标准传输语法(低层数据表示方法)和ORB之间通信的信息格式集。GIOP只能用在ORB与ORB之间,而且,只能在符合理想条件的面向连接传输协议中使用。它不需要使用更高一层的RPC机制。这个协议是简单的(尽可能简单,但不是简单化),可升级的,使用方便。它被设计为可移动的、高效能的表现、较少依靠其它的低层传输协议。当然,由于不同传输使用不同版本的GIOP,它们可能不能直接协作工作,但它能很容易的连接网络域。

IIOP (Internet Inter-ORB Protocol),即Internet对象代理间通信协议,指出如何通过TCP/IP连接交换GIOP信息。IIOP为Internet提供了一个标准的协作工作协议,它使兼容的ORB能基于现在流行的协议和产品进行“out of the box”方式的协作工作。它也能被用于两个半桥(half-bridges )之间的协议。该协议能用于任何ORB与IP(Internet Protocol)域之间的协作工作,除非ORB选择了特殊的协议。这时,它是TCP/IP环境下基本的inter-ORB 协议,最普遍的传输层。

GIOP 不基于任何特别的网络协议,OMG 在最广泛使用的通信传输平台 — TCP/IP 上标准化 GIOP,GIOP 加 TCP/IP 等于 IIOP。

RMI简单示例

1、接口定义

package com.neohope.rmi.test;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * Created by Hansen
 */
public interface ITest extends Remote {
    /**
     * 返回“Hi XXX"字符串,必须声明抛出RemoteException异常
     * @return 返回“Hi XXX"字符串
     * @throws java.rmi.RemoteException
     */
    public String sayHiTo(String user) throws RemoteException;

    /**
     * 加法,必须声明抛出RemoteException异常
     * @param a
     * @parma b
     * @return a+b
     * @throws java.rmi.RemoteException
     */
    public int add(int a, int b) throws RemoteException;
}

2、服务端实现

package com.neohope.rmi.test;

import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/**
 * Created by Hansen
 */
public class TestServer implements ITest, Serializable {

    /**
     * 构造函数,必须声明抛出RemoteException异常
     *
     * @throws RemoteException
     */
    public TestServer() throws RemoteException {
    }

    /**
     * 返回“Hi XXX"字符串
     * @return 返回“Hi XXX"字符串
     * @throws java.rmi.RemoteException
     */
    @Override
    public String sayHiTo(String user) throws RemoteException {
        return "Hi " + user;
    }

    /**
     * 加法
     * @param a
     * @parma b
     * @return a+b
     * @throws java.rmi.RemoteException
     */
    @Override
    public int add(int a, int b) throws RemoteException {
        return a+b;
    }

    public static void main(String[] args) throws IOException, AlreadyBoundException {
        //创建一个远程对象
        ITest server = new TestServer();
        //注册端口
        LocateRegistry.createRegistry(1234);
        //绑定对象
        Naming.bind("rmi://localhost:1234/RemoteTest", server);

        System.in.read();
    }
}

3、客户端实现

package com.neohope.rmi.test;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
 * Created by Hansen
 */
public class TestClient {
    public static void main(String args[]) throws RemoteException, NotBoundException, MalformedURLException {
        //查找服务,并调用方法
        ITest rservice = (ITest) Naming.lookup("rmi://localhost:1234/RemoteTest");
        System.out.println(rservice.sayHiTo("neohope"));
        System.out.println(rservice.add(1,2));
    }
}

XMLRPC简单示例

1、客户端实现

package com.neohope.xmlrpc.test;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Vector;

/**
 * Created by Hansen
 */
public class TestClient {
    public static void main(String[] args) throws MalformedURLException, XmlRpcException {
        //设置服务地址
        XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
        config.setServerURL(new URL("http://localhost:8080/XmlRpcTest"));
        //config.setServerURL(new URL("http://localhost:1234/xmlrpc"));
        XmlRpcClient client = new XmlRpcClient();
        client.setConfig(config);

        //调用方法
        Vector<String> params1 = new Vector<String>();
        params1.addElement("neohope");
        String result1 = (String) client.execute("ITest.sayHiTo", params1);
        System.out.println(result1);

        Vector<Integer> params2 = new Vector<Integer>();
        params2.addElement(1);
        params2.addElement(2);
        int result2 = (int) client.execute("ITest.add", params2);
        System.out.println(result2);
    }
}

2、服务端接口定义

package com.neohope.xmlrpc.test;

/**
 * Created by Hansen
 */
public interface ITest{
    /**
     * 返回“Hi XXX"字符串,必须声明抛出RemoteException异常
     * @return 返回“Hi XXX"字符串
     */
    public String sayHiTo(String user);

    /**
     * 加法,必须声明抛出RemoteException异常
     * @param a
     * @parma b
     * @return a+b
     */
    public int add(int a, int b);
}

3、基于WebServer的服务端实现

package com.neohope.xmlrpc.test;

import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServer;
import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
import org.apache.xmlrpc.webserver.WebServer;

/**
 * Created by Hansen
 */
public class TestServer implements ITest {
    /**
     * 返回“Hi XXX"字符串
     * @return 返回“Hi XXX"字符串
     * @throws java.rmi.RemoteException
     */
    @Override
    public String sayHiTo(String user) {
        return "Hi " + user;
    }

    /**
     * 加法
     * @param a
     * @parma b
     * @return a+b
     * @throws java.rmi.RemoteException
     */
    @Override
    public int add(int a, int b) {
        return a+b;
    }


    public static void main(String [] args) throws Exception {
        WebServer webServer = new WebServer(1234);
        XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
        PropertyHandlerMapping phm = new PropertyHandlerMapping();
        phm.addHandler("ITest", TestServer.class);
        xmlRpcServer.setHandlerMapping(phm);

        XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl)xmlRpcServer.getConfig();
        serverConfig.setEnabledForExtensions(true);
        serverConfig.setContentLengthOptional(false);
        webServer.start();

    }
}

4、基于Servlet的服务端实现

package com.neohope.xmlrpc.test;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
import org.apache.xmlrpc.webserver.XmlRpcServletServer;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by Hansen
 */
public class TestServlet extends HttpServlet {
    private XmlRpcServletServer rpcserver;

    public void init(ServletConfig pConfig) throws ServletException {

        super.init(pConfig);

        try {
            rpcserver = new XmlRpcServletServer();
            PropertyHandlerMapping phm = new PropertyHandlerMapping();
            phm.addHandler("ITest", TestServer.class);
            rpcserver.setHandlerMapping(phm);

            XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl)rpcserver.getConfig();
            serverConfig.setEnabledForExtensions(true);
            serverConfig.setContentLengthOptional(false);

        } catch (XmlRpcException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void doPost(HttpServletRequest pRequest, HttpServletResponse pResponse) throws IOException, ServletException {
        rpcserver.execute(pRequest, pResponse);
    }

    @Override
    public void doGet(HttpServletRequest pRequest, HttpServletResponse pResponse) throws IOException, ServletException {
        pResponse.getOutputStream().print("It is working.");
    }
}

4、基于Servlet的服务端配置

    <servlet>
        <servlet-name>XmlRpcTest</servlet-name>
        <servlet-class>com.neohope.xmlrpc.test.TestServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>XmlRpcTest</servlet-name>
        <url-pattern>/XmlRpcTest</url-pattern>
    </servlet-mapping>

Quartz入门03

接下来,我们用Cron表达式加配置文件的方式,写一个简单的例子

1、首先是任务类
1.1、Job001

package com.neohope.quartz.test;

import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * Created by Hansen
 */
public class Job001 implements Job {
    private static Logger logger = LoggerFactory.getLogger(Job001.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        logger.info("Job001 Executing : " + new Date());

        //获取Job的参数
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        //String jobDesc = jobDetail.getDescription();

        JobDataMap dataMap = jobDetail.getJobDataMap();
        String message = dataMap.getString("JOB_MSG");
        logger.info("Job001 Message is : " + message);

    }
}

1.2、Job002

package com.neohope.quartz.test;

import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * Created by Hansen
 */
public class Job002 implements Job {
    private static Logger logger = LoggerFactory.getLogger(Job002.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        logger.info("Job002 Executing : " + new Date());

        //获取Job的参数
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        //String jobDesc = jobDetail.getDescription();

        JobDataMap dataMap = jobDetail.getJobDataMap();
        String message = dataMap.getString("JOB_MSG");
        logger.info("Job002 Message is : " + message);
    }
}

2、然后是测试类

package com.neohope.quartz.test;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;


/**
 * Created by Hansen
 */
public class Test002 {

    public void run() throws Exception {
        Logger logger = LoggerFactory.getLogger(Test002.class);

        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler scheduler = sf.getScheduler();

        scheduler.start();
        logger.info("scheduler started");

        try {
            System.in.read();
        } catch (Exception e) {
        }

        scheduler.shutdown(true);
        logger.info("scheduler ended");
    }

    public static void main(String[] args) throws Exception {
        System.setProperty("org.quartz.properties","quartzN.properties");

        Test002 test = new Test002();
        test.run();
    }
}

3、Quartz配置文件

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
org.quartz.scheduler.instanceName: NeoScheduler
org.quartz.scheduler.instanceId: AUTO
org.quartz.scheduler.skipUpdateCheck: true

#============================================================================
# Configure ThreadPool  
#============================================================================
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 1
org.quartz.threadPool.threadPriority: 5

#============================================================================
# Configure JobStore  
#============================================================================
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

#org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
#org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.useProperties: false
#org.quartz.jobStore.dataSource: myDS
#org.quartz.jobStore.tablePrefix: QRTZ_
#org.quartz.jobStore.isClustered: false

#============================================================================
# Configure Datasources  
#============================================================================
#org.quartz.dataSource.myDS.driver: org.postgresql.Driver
#org.quartz.dataSource.myDS.URL: jdbc:postgresql://localhost/dev
#org.quartz.dataSource.myDS.user: jhouse
#org.quartz.dataSource.myDS.password: 
#org.quartz.dataSource.myDS.maxConnections: 5

#============================================================================
# Configure Plugins
#============================================================================
org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames: quartzNScheduler.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound: true
org.quartz.plugin.jobInitializer.scanInterval: 120
org.quartz.plugin.jobInitializer.wrapInUserTransaction: false

4、任务配置文件

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
    version="1.8">
    
    <pre-processing-commands>
        <!-- clear all jobs in scheduler -->
        <delete-jobs-in-group>*</delete-jobs-in-group>
        <!-- clear all triggers in scheduler -->
        <delete-triggers-in-group>*</delete-triggers-in-group>
    </pre-processing-commands>
    
    <processing-directives>
        <!-- if there are any jobs/trigger in scheduler of same name (as in this file), overwrite them -->
        <overwrite-existing-data>true</overwrite-existing-data>
        <!-- if there are any jobs/trigger in scheduler of same name (as in this file),
        and over-write is false, ignore them rather then generating an error -->
        <ignore-duplicates>false</ignore-duplicates> 
    </processing-directives>
    
    <schedule>
        <job>
            <name>Job001</name>
            <group>JGroup001</group>
            <job-class>com.neohope.quartz.test.Job001</job-class>
            <job-data-map>
                <entry>
                    <key>JOB_MSG</key>
                    <value>Hi Job001</value>
                </entry>
            </job-data-map>
        </job>

        <trigger>
            <simple>
                <name>Trigger001</name>
                <group>TGroup001</group>
                <job-name>Job001</job-name>
                <job-group>JGroup001</job-group>
                <!--start-time>2010-02-09T10:15:00</start-time-->
                <!--end-time>2012-02-09T12:26:00.0</end-time-->
                <misfire-instruction>MISFIRE_INSTRUCTION_SMART_POLICY</misfire-instruction>
                <repeat-count>3</repeat-count>
                <repeat-interval>1000</repeat-interval>
            </simple>
        </trigger>

	    <job>
	        <name>Job002</name>
            <group>JGroup002</group>
            <description>Job002</description>
            <job-class>com.neohope.quartz.test.Job002</job-class>
            <job-data-map>
                <entry>
                    <key>JOB_MSG</key>
                    <value>Hi Job002</value>
                </entry>
            </job-data-map>
	    </job>

	    <trigger>
	        <cron>
	            <name>Trigger002</name>
	            <group>TGroup002</group>
	            <job-name>Job002</job-name>
	            <job-group>JGroup002</job-group>
                <!--start-time>2010-02-09T12:26:00.0</start-time-->
                <!--end-time>2012-02-09T12:26:00.0</end-time-->
                <misfire-instruction>MISFIRE_INSTRUCTION_SMART_POLICY</misfire-instruction>
                <cron-expression>0/10 * * * * ? *</cron-expression>
	        </cron>
	    </trigger>
    </schedule>    
</job-scheduling-data>

5、大家运行一下看看吧

Quartz入门02

在正式部署时,任务执行的规则不会很简单,Quartz通过Cron表达式来解决这个问题。

Cron表达式的格式为:
[秒] [分] [时] [日] [月] [星期] [年]

各字段填写规则为:

字段 是否必填 允许值 允许通配符
YES 0-59 , – * /
YES 0-59 , – * /
YES 0-23 , – * /
YES 1-31 , – * ? / L W
YES 1-12 or JAN-DEC , – * /
星期 YES 1-7 or SUN-SAT , – * ? / L #
NO empty, 1970-2099 , – * /

通配符含义为:

* 表示所有值 在分的字段上设置 “*”,表示每一分钟都会触发。
? 表示不指定值,不需要关心当前设置这个字段的值 要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为”?” 具体设置为 0 0 0 10 * ?
表示区间 在小时上设置 “10-12”,表示 10,11,12点都会触发。
, 表示指定多个值 在周字段上设置 “MON,WED,FRI” 表示周一,周三和周五触发
/ 用于递增触发 在秒上面设置”5/15″,表示从5秒开始,每增15秒触发(5,20,35,50)。在月字段上设置’1/3’所示每月1号开始,每隔三天触发一次。
L 表示最后的意思。 在日字段设置上,表示当月的最后一天, 在日期字段上表示星期六,相当于”7″或”SAT”。如果在”L”前加上数字,则表示该数据的最后一个。在周字段上设置”6L”这样的格式,则表示“本月最后一个星期五”
W 表示离指定日期的最近那个工作日(周一至周五) 例如在日字段上设置”15W”,表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发。如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 “1W”,它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,”W”前只能设置具体的数字,不允许区间”-“)。’L’和’W’可以一组合使用。如果在日字段上设置”LW”,则表示在本月的最后一个工作日触发
# 序号(表示每月的第几个周几) 例如在周字段上设置”6#3″表示在每月的第三个周六。注意果指定”6#5″,正好第五周没有周六,则不会触发该配置

官网上的示例:

表达式 含义
0 0 12 * * ? Fire at 12pm (noon) every day
0 15 10 ? * * Fire at 10:15am every day
0 15 10 * * ? Fire at 10:15am every day
0 15 10 * * ? * Fire at 10:15am every day
0 15 10 * * ? 2005 Fire at 10:15am every day during the year 2005
0 * 14 * * ? Fire every minute starting at 2pm and ending at 2:59pm, every day
0 0/5 14 * * ? Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day
0 0/5 14,18 * * ? Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day
0 0-5 14 * * ? Fire every minute starting at 2pm and ending at 2:05pm, every day
0 10,44 14 ? 3 WED Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.
0 15 10 ? * MON-FRI Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday
0 15 10 15 * ? Fire at 10:15am on the 15th day of every month
0 15 10 L * ? Fire at 10:15am on the last day of every month
0 15 10 L-2 * ? Fire at 10:15am on the 2nd-to-last last day of every month
0 15 10 ? * 6L Fire at 10:15am on the last Friday of every month
0 15 10 ? * 6L Fire at 10:15am on the last Friday of every month
0 15 10 ? * 6L 2002-2005 Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005
0 15 10 ? * 6#3 Fire at 10:15am on the third Friday of every month
0 0 12 1/5 * ? Fire at 12pm (noon) every 5 days every month, starting on the first day of the month.
0 11 11 11 11 ? Fire every November 11th at 11:11am.