【CSII-PE】报文配置为何要加前缀fseg?

最近一直在好奇一个问题,为什么PE框架在发报文的时候报文名字有个前缀fseg呢?为了解决心中的疑惑,去项目上找找代码一探究竟。
首先发送报文一定要引用transport,先看看transport里有什么东东。

<!-- 对接esb -->
<transport id="ESBXMLTransformerTransport" class="com.csii.cop.transport.XmlTransport">
    //报文解析
    <ref name="transformerFactory">ESBTransformerFactory</ref>
    //socket通讯
    <ref name="transport">ESBSimpleXMLTcpTransport</ref>
    //响应报文特殊处理
    <ref name="streamParser">StreamParser</ref>
    //报文格式
    <param name="formatName">XMLOutboundPacketESB</param>
    //响应报文解析器
    <param name="parseName">esbxmlPacketParser</param>
    <param name="debug">true</param>
    //打印日志路径
    <param name="dumpPath">/home/weblogic/tmp</param>
    //报文是否打印在日志里
    <param name="singleLogFile">true</param>
</transport>

如果要发送报文,一定要调用transport.submit()方法,找到对应的transport实现类看下

@Override
public Object submit(Object obj) throws CommunicationException {
    if (this.throttlePolicy != null) {
        Object id = this.throttlePolicy.acquire(obj, 0);
        if (id != null) {
            try {
                return submitInner(obj);
            } finally {
                this.throttlePolicy.free(id);
            }

        }

        throw new ThrottleRejectException("");
    }

    return submitInner(obj);
}

可以看到具体的逻辑是在submitInner()方法中,进去看下

private Object submitInner(Object input) throws CommunicationException {
    setInputData((Map) input);
    try {
        //获取报文树解析器(XMLOutboundPacketESB)
        Transformer formater = this.transformerFactory.getTransformer(this.formatName);
        if (this.headFormatter != null) {
            input = this.headFormatter.format(input, (Map) input);
        }
        //组装发送报文数据
        Object preData = formater.format(input, (Map) input);
    //省略部分代码
    } catch (TransformException e) {
        throw new CommunicationException(e.getMessageKey(), e);
    } finally {
        unsetInputData();
    }
}

此段代码可以看到formater.format()方法是关键,那么是如何实现的呢,transformerFactory.getTransformer()这个方法提示了我们寻找的方向。
找到transformerFactory声明位置

<!-- 对接ESB -->
<bean name="ESBTransformerFactory" class="com.csii.pe.transform.XmlTransformerFactory">
    <param name="path">/META-INF/config/outbound/csxml/packets</param>
    <param name="debug">false</param>
    <param name="cacheEnable">false</param>
    <map name="parsers">
        <ref name="esbxmlPacketParser">esbXmlPacketParser</ref>
    </map>
</bean> 

 /META-INF/config/outbound/csxml/packets 为报文存放路径
查看实现类XmlTransformerFactory

public class XmlTransformerFactory extends TransformerFactory {

    public void setParsers(Map parsers) {
        Iterator it = parsers.entrySet().iterator();

        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            //获取key和value
            super.addTransformer((String) entry.getKey(), (Transformer) entry.getValue());
        }

    }
}

查看实现类XmlTransformerFactory父类TransformerFactory的addTransformer方法实现逻辑

public Element getElement(String id) {
    Element element;
    if (this.cacheEnable) {
        element = (Element) this.cache.get(id);
        if (element != null) {
            return element;
        }
    }
    
    element = (Element) this.elements.get(id);
    if (element == null) {
        //找交易报文配置
        element = (Element) this.getObject(this.pathPrefix + id + ".xml");
    }

    if (element == null) {
        throw new PeRuntimeException("can\'t find :" + this.pathPrefix + id + ".xml");
    } else {
        if (element != null && element instanceof ElementFactoryAware) {
            ((ElementFactoryAware) element).setElementFactory(this);
        }

        this.cache.put(id, element);
        return element;
    }
}

到目前位置,找到的是公共报文配置XMLOutboundPacketESB.xml。

<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE segment SYSTEM "packet.dtd">
<Group name="Transaction" xmlHead="&lt;?xml version=&quot;1.0&quot; encoding=&quot;gbk&quot;?&gt;">
    <Group name="Header">
        <Group name="sysHeader">
            <xmlTag tagName="msgId"> <String name="msgId" ></String></xmlTag>
            <xmlTag tagName="msgDate" ><String name="msgDate"></String></xmlTag>
            <xmlTag tagName="msgTime" ><String name="msgTime"></String></xmlTag>
            <xmlTag tagName="serviceCd" ><String name="serviceCd"></String></xmlTag>
            <xmlTag tagName="operation" ><String name="operation"></String></xmlTag>
            <xmlTag tagName="clientCd" ><String name="clientCd" defaultValue="277"></String></xmlTag>
            <xmlTag tagName="serverCd" ><String name="serverCd" ></String></xmlTag> 
            <xmlTag tagName="bizId" ><String name="bizId" ></String></xmlTag> 
            <xmlTag tagName="bizType" ><String name="bizType" ></String></xmlTag> 
            <xmlTag tagName="orgCode" ><String name="orgCode" defaultValue="01001"></String></xmlTag> 
            <xmlTag tagName="resCode" ><String name="resCode" ></String></xmlTag> 
            <xmlTag tagName="resText" ><String name="resText" ></String></xmlTag> 
            <xmlTag tagName="bizResCode" ><String name="bizResCode" ></String></xmlTag> 
            <xmlTag tagName="bizResText" ><String name="bizResText" ></String></xmlTag> 
            <xmlTag tagName="authId" ><String name="authId" ></String></xmlTag> 
            <xmlTag tagName="authPara" ><String name="authPara" ></String></xmlTag> 
            <xmlTag tagName="authContext" ><String name="authContext" ></String></xmlTag> 
            <xmlTag tagName="pinIndex" ><String name="pinIndex" ></String></xmlTag> 
            <xmlTag tagName="pinValue" ><String name="pinValue" ></String></xmlTag> 
            <xmlTag tagName="ver" ><String name="ver" ></String></xmlTag> 
        </Group>
    </Group>
    <Group name="Body">
        <Group name="request">
            <Group name="bizHeader">
                <include keyName="biz"></include>
            </Group>
            <Group name="bizBody">
                <include keyName="_HostTransactionCode"></include>
            </Group>
        </Group>
    </Group>
</Group>


注意,<include keyName="_HostTransactionCode"></include>这句话写出了我们交易将要使用的报文名称
回头看下formater.format()具体实现类XmlSegment.calss

public class XmlSegment extends Segment {

    private byte[] xmlHeadBytes;
    private String tagName;
    private byte[] endXml;
    private String includePrefix = "fseg";//不远万里,终于找到你
    private byte[] beginXml;
    private Map attributes;
    private Expr expr;
    private boolean option = true;
    private String xmlHead;
    private boolean format = false;
    private boolean skipBody = false;
    private static final String NEWLINE = "\r\n";
    private static final byte[] NEWLINEBYTES = "\r\n".getBytes();
    private static Pattern pattern = Pattern.compile("([^={}]{1,})=\\{([^{}]{1,})\\}");

    public Object format(Object data, Map context) throws TransformException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        this.format(out, data, context);
        return out.toByteArray();
    }

    public void format(OutputStream out, Object data, Map context) throws TransformException {
        try {
                if (!this.skipBody) {
                    for (int i = 0; i < this.elements.size(); ++i) {
                        Element ele = (Element) this.elements.get(i);
                        if (ele instanceof Format2Stream) {
                            if (ele instanceof Segment) {
                                Object obj = ((Map) data).get(ele.getName());
                                if (obj == null) {
                                    ((Format2Stream) ele).format(out, data, (Map) data);
                                } else {
                                    ((Format2Stream) ele).format(out, obj, (Map) data);
                                }
                            } else {
                                ((Format2Stream) ele).format(out, ((Map) data).get(ele.getName()), (Map) data);
                            }
                        } else if (ele instanceof TransformerElement) {
                            
                        } else if (ele instanceof Include) {
                            Include include = (Include) ele;
                            String condition = include.getCondition();
                            if (condition != null) {
                                OgnlExpr includeT = new OgnlExpr();
                                boolean includedData = ((Boolean) includeT.getValue(condition, (Map) data, (Map) data)).booleanValue();
                                if (!includedData) {
                                    continue;
                                }
                            }
                            //fseg最终在这里使用includePrefix = fseg
                            Transformer transformer = (Transformer) include.getElement(this.includePrefix, (Map) data);
                           
                        }
                    }
                }

                out.write(this.endXml);
                if (this.format) {
                    out.write(NEWLINEBYTES);
                }
            }
        } catch (Exception arg10) {
            throw new TransformException(this.getClass().getName() + ".format error: " + this.getName(), arg10);
        }
    }
}

原来是XmlSegment.calss加了fseg,不远万里,终于找到你

by CSII@王大仙

猜你喜欢

转载自blog.csdn.net/joxlin/article/details/81630942