Jpos体系结构

一、   ISOComponet

 

 


 

这里ISOFieldISOBitMap都是实现了ISOComponent的叶子节点,ISOMsg则是包含了ISOFieldComposite (组合类):ISOMsg类维护了Hashtable fields,维护了该报文的所有的位元。

 

参考:composite模式

ISOComponent类体系采用composite模式,为的是能够以统一的方式处理基本元素和复合元素(The Composite Design pattern allows a client object to treat both single components and collections of components identically.   

实现Composite pattern相对比较容易,Composite classes extend a base class that represents primitive objects. Figure 1 shows a class diagram that illustrates the Composite pattern's structure

Component是一个接口或者抽象类,定义了叶子节点和Composite节点的公共方法;Composite类维护了Component的一个集合,提供了对该集合操作的一些方法,比如addComponent()removeComponent(),同时也包括了叶子节点的操作方法。该模式的

ISOBitMap

封装了protected BitSet value;并且提供了维护该bitmap的方法

三、   ISOMsg

包括fieldsheaderdirection,消息类型是在第0号位元存放的

 

四、   ISOFieldPackager

ISOFieldPackager抽象了iso8583的位元的封装方式,定义了位元的抽象特性和一些模版方法,比如packunpack方法

ISOFieldPackager的几个子类比如ISOStringFieldPackager分别适用于不同的报文的编码方式,每种不同的编码方式都包括了三个成员类:InterpreterpaderPrefixer,分别用于负责转换位元内容、插入填充内容和插入位元长度。

因此通过继承每一种不同的编码方式的之类,jpos提供了不同的具体的ISO的数据类型类。InterpreterPaderPrefixer接口的具体实现通过构造函数传入ISO的数据类型类。


五、   Prefixer(域前缀信息)

其中Prefixer指得是ISOField得域长度信息。有两个主要方法:

void encodeLength(int length, byte[] b) throws ISOException;

int decodeLength(byte[] b, int offset) throws ISOException;

第一个方法是根据length产生长度得编码信息,存放到byte b[]中,比如encodeLength(21, byte[] b),就是把对21编码,生成编码信息存放到b[0]b[1]当中。

Length含义的解释:代表该域的实际长度,比如某一个域定义的是LL..99,则length可以是0..99之间的任何数。

第二个方法是对第一个方法的逆向操作

参见AsciiPrefixer的源码

 

六、   InterPreter(翻译器)

InterPreter接口有下面三个方法:

1void interpret(String data, byte[] b, int offset)

String格式的data转换成为byte数组

Converts the string data into a different interpretationStandard interpretations are ASCII, EBCDIC, BCD and LITERAL

2String uninterpret(byte[] rawData, int offset, int length)

Converts the byte array into a String. This reverses the interpret method.

byte数组中的内容转换回String格式

3int getPackedLength(int nDataUnits)

 

七、   Padder接口(填充器)

An interface for padding and unpadding strings and byte arrays。根据不同情况有多种填充策略,包括LeftPadder,RightPadder,RightTPadder等。

String pad(String data, int maxLength) throws ISOException;  用于填充String或者Byte数组在实际长度和定义的长度之间的空白位

String unpad(String paddedData) throws ISOException;  去除实际长度和定义的长度之间填充的空白

八、   ISOPackager


ISOPackager类为整个iso8583报文,包含了全部128个域的定义。ISO87ApackagerISO93Apackager等类为一些重要和常用的某个具体的协议硬编码好了完整的位元信息,包括每个位元的代码,描叙和处理类(FieldPackager)。

在具体使用的时候,可以直接使用这些报文处理类,也可以使用GeneriaPackager类来根据具体读取报文协议信息,比如config/packager/iso87ascii.xml ,可以很方便地切换协议。

 

九、   ISOFilter

An ISOFilter has the oportunity to modify an incoming or outgoing ISOMsg that is about to go thru an ISOChannel. It also has the chance to Veto by throwing an Exception

ISOFilter除了能够修改通过ISOChannel接受和发送的ISOMsg以外,还能够通过抛出异常的方式终止ISOMsg的接受和发送。

public ISOMsg filter (ISOChannel channel, ISOMsg m, LogEvent evt)  throws VetoException;

十、   ISORequest

 

 

十一、      ISOResponse

 

 

 

十二、ISOChannel

Allows the transmision and reception of ISO 8583 MessagesIn any case the programmer implementing the high level application logic must not deal with packaging and interchange low level details. The helper class ISOChannel takes care of that.

ISOChannel用来完成底层的packageinterchange,是应用层与底层细节的一个联系纽带。这个类负责完成报文的发送和接收,接收的参数包括:ISOPackagerServerSocket或者hostport


 

接口的方法签名:

public void setPackager(ISOPackager p);

public void connect () throws IOException;

public void disconnect () throws IOException;

public void reconnect() throws IOException;

public boolean isConnected();

public ISOMsg receive() throws IOException, ISOException;

public void send (ISOMsg m) throws IOException, ISOException;

public void setUsable(boolean b);

从上面可以看出,ISOChannel的职责包括:

1)       通过调用相应的Packager完成Fieldpadderintercpetprefix或者反向操作;

2)       创建并维护connnection

3)       发送ISOMsg(包括发送请求报文和发送应答报文)

(4)       根据传输过来的报文,创建ISOMsg(包括接收请求报文和接收应答报文)

 

大部分的实现逻辑常见org.jpos.BaseChanel.java

public void send(ISOMsg m) throws IOException, ISOException, VetoException

public ISOMsg receive() throws IOException, ISOException

 

public abstract class BaseChannel extends Observable implements

       FilteredChannel, ClientChannel, ServerChannel, FactoryChannel,

       LogSource, ReConfigurable, BaseChannelMBean {

 

详细见ISOBaseChannelsendreceive方法

 

十三、      ISOMUX

An ISOMUX is a runnable class that asynchronously handles multiplexing and demultiplexing of ISOMsgs over a single ISOChannel.

The multiplexing/demultiplexing is based on the protected function ISOMUX.getKey(). The default implementation returns the concatenated (zero padded) values of fields 41 + field 11 (TerminalID+TraceNumber). You can subclass to provide different behaviour.

ISOMUX allows multiple terminals in a LAN or WAN to asynchronously send and receive messages over a single ISOChannel link. It also automatically handles ISOChannel reconnections.


ISOMUX用来异步地处理某一个特定渠道发来的重发报文。ISOMUX为作为ISOChannel的前端fascade,供发送客户端调用。 

ISOMUX.getKey()返回报文中的11位元(交易系统生成的流水号)和41位元(终端标识码)的组合,可以用来唯一识别某比具体的交易。

 

十四、      ISOServer

 

十五、      ServerChannel

服务器方接收接口,使用了java socket编程接口;需要区别于客户端的接收应答的实现方式

 

public interface ServerChannel extends ISOChannel {

   /**

    * Accepts connection

    * @exception IOException

    */

    public void accept(ServerSocket s) throws IOException;

}

服务器端,实现方法在BaseChannel类中

public void accept(ServerSocket s) throws IOException {

        connect(s.accept());

    }

 

protected void connect(Socket socket) throws IOException, SocketException {

       this.socket = socket;

       applyTimeout();

       setLogger(getLogger(), getOriginalRealm() + "/"

              + socket.getInetAddress().getHostAddress() + ":"

              + socket.getPort());

       serverIn = new DataInputStream(new BufferedInputStream(socket

              .getInputStream()));

       serverOut = new DataOutputStream(new BufferedOutputStream(socket

              .getOutputStream(), 2048));

       usable = true;

       cnt[CONNECT]++;

       setChanged();

       notifyObservers();

    }

 

这样接收到的数据可以从serverIn中获取,发送应答可以通过serverOut

 

十六、      协议

发送报文:

m.set(new ISOField(0, "0200"));

m.set(new ISOField(11, "1")); //6位定长数字,前补零

m.set(new ISOField(41, "11"));//8位定长字符,后补空

m.set(new ISOField(44,"nihao")); //25位变长字符

 

发送报文串如下

020000200000009