Apache XML-RPC 是 一个 Java 语言对 XML-RPC 协议的封装。XML-RPC协议是通过HTTP之上传输XML片段来实现远程方法调用。
在使用apache-xmlrpc-3.1.3作为XML-RPC客户端时无法在日志查看消息交互的码流,只能通过抓包工具抓包分析,所以修改了下apache-xmlrpc的源码,以支持通过日志来显示交互XML码流信息。
加入监听器:
package org.apache.xmlrpc;
/**
* XmlRpc消息监听器
*
* @author Administrator<br/>
* @version <br/>
* @email: zcg@suntektech.com<br/>
* @datetime: 2012-8-28 <br/>
*/
public interface XmlRpcMessageListener {
/**
* 回调,包括客户端请求和服务端响应的XML字符串内容
*
* @param xmlContent
*/
void onMessage(String xmlContent);
}
客户端修改:
public Object sendRequest(XmlRpcRequest pRequest) throws XmlRpcException {
XmlRpcStreamRequestConfig config = (XmlRpcStreamRequestConfig) pRequest.getConfig();
boolean closed = false;
try {
ReqWriter reqWriter = newReqWriter(pRequest);
// added by zcg 2012-08-28,客户端显示发送请求的XML日志
if (reqWriter instanceof XmlRpcHttpTransport.ByteArrayReqWriter && getListener() != null) {
XmlRpcHttpTransport.ByteArrayReqWriter tmpWriter = (XmlRpcHttpTransport.ByteArrayReqWriter) reqWriter;
// System.out.println(tmpWriter.getContentString());
getListener().onMessage(tmpWriter.getContentString());
}
writeRequest(reqWriter);
InputStream istream = getInputStream();
if (isResponseGzipCompressed(config)) {
istream = new GZIPInputStream(istream);
}
Object result = readResponse(config, istream);
closed = true;
close();
return result;
} catch (IOException e) {
throw new XmlRpcException("Failed to read server's response: " + e.getMessage(), e);
} catch (SAXException e) {
Exception ex = e.getException();
if (ex != null && ex instanceof XmlRpcException) {
throw (XmlRpcException) ex;
}
throw new XmlRpcException("Failed to generate request: " + e.getMessage(), e);
} finally {
if (!closed) {
try {
close();
} catch (Throwable ignore) {
}
}
}
}
protected Object readResponse(XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException {
// added by zcg 2012-09-06 客户端显示收到响应的XML日志
if (getListener() != null) {
StringBuilder builder = new StringBuilder();
BufferedReader r = null;
try {
r = new BufferedReader(new InputStreamReader(pStream));
String line = "";
while ((line = r.readLine()) != null) {
builder.append(line).append("\n");
}
getListener().onMessage(builder.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (r != null) {
try {
r.close();
} catch (IOException e) {
}
}
}
String str = builder.toString();
pStream = new ByteArrayInputStream(str.getBytes());
}
InputSource isource = new InputSource(pStream);
XMLReader xr = newXMLReader();
XmlRpcResponseParser xp;
try {
xp = new XmlRpcResponseParser(pConfig, getClient().getTypeFactory());
xr.setContentHandler(xp);
xr.parse(isource);
} catch (SAXException e) {
throw new XmlRpcClientException("Failed to parse server's response: " + e.getMessage(), e);
} catch (IOException e) {
throw new XmlRpcClientException("Failed to read server's response: " + e.getMessage(), e);
}
if (xp.isSuccess()) {
return xp.getResult();
}
Throwable t = xp.getErrorCause();
if (t == null) {
throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage());
}
if (t instanceof XmlRpcException) {
throw (XmlRpcException) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage(), t);
}
服务端修改:
/**
* Returns, whether the /** Processes a "connection". The "connection" is an
* opaque object, which is being handled by the subclasses.
*
* @param pConfig
* The request configuration.
* @param pConnection
* The "connection" being processed.
* @throws XmlRpcException
* Processing the request failed.
*/
public void execute(XmlRpcStreamRequestConfig pConfig, ServerStreamConnection pConnection) throws XmlRpcException {
log.debug("execute: ->");
try {
Object result;
Throwable error;
InputStream istream = null;
try {
istream = getInputStream(pConfig, pConnection);
{
// added by zcg 2012-09-06
if (getListener() != null) {
StringBuilder builder = new StringBuilder();
BufferedReader r = null;
try {
r = new BufferedReader(new InputStreamReader(istream));
String line = "";
while ((line = r.readLine()) != null) {
builder.append(line).append("\n");
}
getListener().onMessage(builder.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (r != null) {
r.close();
}
}
String str = builder.toString();
istream = new ByteArrayInputStream(str.getBytes());
}
}
XmlRpcRequest request = getRequest(pConfig, istream);
result = execute(request);
istream.close();
istream = null;
error = null;
log.debug("execute: Request performed successfully");
} catch (Throwable t) {
logError(t);
result = null;
error = t;
} finally {
if (istream != null) {
try {
istream.close();
} catch (Throwable ignore) {
}
}
}
boolean contentLengthRequired = isContentLengthRequired(pConfig);
ByteArrayOutputStream baos;
OutputStream ostream;
if (contentLengthRequired) {
baos = new ByteArrayOutputStream();
ostream = baos;
} else {
baos = null;
ostream = pConnection.newOutputStream();
}
ostream = getOutputStream(pConnection, pConfig, ostream);
try {
if (error == null) {
writeResponse(pConfig, ostream, result);
} else {
writeError(pConfig, ostream, error);
}
ostream.close();
ostream = null;
} finally {
if (ostream != null) {
try {
ostream.close();
} catch (Throwable ignore) {
}
}
}
if (baos != null) {
// added by zcg 2012-08-28
if (getListener() != null) {
getListener().onMessage(new String(baos.toByteArray()));
}
OutputStream dest = getOutputStream(pConfig, pConnection, baos.size());
try {
baos.writeTo(dest);
dest.close();
dest = null;
} finally {
if (dest != null) {
try {
dest.close();
} catch (Throwable ignore) {
}
}
}
}
pConnection.close();
pConnection = null;
} catch (IOException e) {
throw new XmlRpcException("I/O error while processing request: " + e.getMessage(), e);
} finally {
if (pConnection != null) {
try {
pConnection.close();
} catch (Throwable ignore) {
}
}
}
log.debug("execute: <-");
}
客户端使用方法:
XmlRpcClient instance = new XmlRpcClient();
// apache xmlrpc客户端配置信息
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL(url));
config.setConnectionTimeout(2 * 1000);
config.setReplyTimeout(30 * 1000);
// 允许使用apache xmlrpc的扩展功能
config.setEnabledForExtensions(true);
// 设置为true,服务端抛出异常客户端将能够捕捉到
config.setEnabledForExceptions(true);
// 生成xmlrpc客户端
instance.setTransportFactory(new XmlRpcLite14HttpTransportFactory(instance));
instance.setConfig(config);
instance.setListener(new VvmgwXmlRpcClientHandler());
服务端使用方法:
public class XmlRpcServerServlet extends XmlRpcServlet implements XmlRpcMessageListener {
private static LogProxy logger = LogHandler.getLogger();
/**
* Creates a new handler mapping. The default implementation loads a
* property file from the resource <code>/XmlRpcServlet.properties</code>
*/
protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException {
URL url = XmlRpcServerServlet.class.getResource("/resources/xmlrpc-config.properties");
if (url == null) {
throw new XmlRpcException("Failed to locate resource xmlrpc-config.properties");
}
try {
return newPropertyHandlerMapping(url);
} catch (IOException e) {
throw new XmlRpcException("Failed to load resource " + url + ": " + e.getMessage(), e);
}
}
public void onMessage(String xmlContent) {
if (logger.isTraceEnabled()) {
logger.trace("Response: " + xmlContent);
}
}
public XmlRpcMessageListener getListener() {
return this;
}
}