Java 使用 JAX-WS 跟踪 XML 请求/响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1945618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Tracing XML request/responses with JAX-WS
提问by Antonio
Is there an easy way (aka: not using a proxy) to get access to the raw request/response XML for a webservice published with JAX-WS reference implementation (the one included in JDK 1.5 and better) ? Being able to do that via code is what I need to do. Just having it logged to a file by clever logging configurations would be nice but enough.
是否有一种简单的方法(又名:不使用代理)来访问使用 JAX-WS 参考实现(包含在 JDK 1.5 和更好的版本中)发布的 Web 服务的原始请求/响应 XML?能够通过代码做到这一点是我需要做的。仅通过巧妙的日志记录配置将其记录到文件中就很好,但已经足够了。
I know that other more complex and complete frameworks exist that might do that, but I would like to keep it as simple as possible and axis, cxf, etc all add considerable overhead that I want to avoid.
我知道存在其他更复杂和完整的框架可以做到这一点,但我希望它尽可能简单,并且轴、cxf 等都增加了我想避免的相当大的开销。
Thanks!
谢谢!
采纳答案by Antonio
Here is the solution in raw code (put together thanks to stjohnroe and Shamik):
这是原始代码中的解决方案(感谢 stjohnroe 和 Shamik):
Endpoint ep = Endpoint.create(new WebserviceImpl());
List<Handler> handlerChain = ep.getBinding().getHandlerChain();
handlerChain.add(new SOAPLoggingHandler());
ep.getBinding().setHandlerChain(handlerChain);
ep.publish(publishURL);
Where SOAPLoggingHandler is (ripped from linked examples):
SOAPLoggingHandler 在哪里(从链接示例中提取):
package com.myfirm.util.logging.ws;
import java.io.PrintStream;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/*
* This simple SOAPHandler will output the contents of incoming
* and outgoing messages.
*/
public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {
// change this to redirect output if desired
private static PrintStream out = System.out;
public Set<QName> getHeaders() {
return null;
}
public boolean handleMessage(SOAPMessageContext smc) {
logToSystemOut(smc);
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
logToSystemOut(smc);
return true;
}
// nothing to clean up
public void close(MessageContext messageContext) {
}
/*
* Check the MESSAGE_OUTBOUND_PROPERTY in the context
* to see if this is an outgoing or incoming message.
* Write a brief message to the print stream and
* output the message. The writeTo() method can throw
* SOAPException or IOException
*/
private void logToSystemOut(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
out.println("\nOutbound message:");
} else {
out.println("\nInbound message:");
}
SOAPMessage message = smc.getMessage();
try {
message.writeTo(out);
out.println(""); // just to add a newline
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
}
回答by rsp
You could try to put a ServletFilter
in front of the webservice and inspect request and response going to / returned from the service.
您可以尝试将 aServletFilter
放在 webservice 的前面并检查进入/从服务返回的请求和响应。
Although you specifically did not ask for a proxy, sometimes I find tcptraceis enough to see what goes on on a connection. It's a simple tool, no install, it does show the data streams and can write to file too.
尽管您没有特别要求代理,但有时我发现tcptrace足以查看连接上发生的情况。这是一个简单的工具,无需安装,它确实显示数据流并且也可以写入文件。
回答by Shamik
One way to do is not using your code but use network packet sniffers like Etheral or WireShark which can capture the HTTP packet with the XML message as payload to it and you can keep logging them to a file or so.
一种方法是不使用您的代码,而是使用网络数据包嗅探器,如 Etheral 或 WireShark,它们可以捕获带有 XML 消息作为负载的 HTTP 数据包,您可以将它们记录到文件左右。
But more sophisticated approach is to write your own message handlers. You can have a look at it here.
但更复杂的方法是编写自己的消息处理程序。你可以在这里看看。
回答by stjohnroe
You need to implement a javax.xml.ws.handler.LogicalHandler, this handler then needs to be referenced in a handler configuration file, which in turn is referenced by an @HandlerChain annotation in your service endpoint (interface or implementation). You can then either output the message via system.out or a logger in your processMessage implementation.
您需要实现一个 javax.xml.ws.handler.LogicalHandler,然后需要在处理程序配置文件中引用该处理程序,该文件又由您的服务端点(接口或实现)中的 @HandlerChain 注释引用。然后,您可以通过 system.out 或 processMessage 实现中的记录器输出消息。
See
看
http://java.sun.com/mailers/techtips/enterprise/2006/TechTips_June06.html
http://java.sun.com/mailers/techtips/enterprise/2006/TechTips_June06.html
回答by skaffman
There are various ways of doing this programmatically, as described in the other answers, but they're quite invasive mechanisms. However, if you know that you're using the JAX-WS RI (aka "Metro"), then you can do this at the configuration level. See here for instructionson how to do this. No need to mess about with your application.
如其他答案中所述,有多种以编程方式执行此操作的方法,但它们是非常具有侵入性的机制。但是,如果您知道您正在使用 JAX-WS RI(又名“Metro”),那么您可以在配置级别执行此操作。有关如何执行此操作的说明,请参见此处。无需弄乱您的应用程序。
回答by Upendra
Before starting tomcat, set JAVA_OPTS
as below in Linux envs. Then start Tomcat. You will see the request and response in the catalina.out
file.
在启动 tomcat 之前,JAVA_OPTS
在 Linux envs 中设置如下。然后启动Tomcat。您将在catalina.out
文件中看到请求和响应。
export JAVA_OPTS="$JAVA_OPTS -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true"
回答by Mr. Napik
Following options enable logging of all communication to the console (technically, you only need one of these, but that depends on the libraries you use, so setting all four is safer option). You can set it in the code like in example, or as command line parameter using -D or as environment variable as Upendra wrote.
以下选项可以将所有通信记录到控制台(从技术上讲,您只需要其中之一,但这取决于您使用的库,因此设置所有四个是更安全的选项)。您可以像示例一样在代码中设置它,或者使用 -D 作为命令行参数,或者作为 Upendra 编写的环境变量。
System.setProperty("com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true");
System.setProperty("com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true");
System.setProperty("com.sun.xml.ws.transport.http.HttpAdapter.dump", "true");
System.setProperty("com.sun.xml.internal.ws.transport.http.HttpAdapter.dump", "true");
System.setProperty("com.sun.xml.internal.ws.transport.http.HttpAdapter.dumpTreshold", "999999");
See question Tracing XML request/responses with JAX-WS when error occursfor details.
有关详细信息,请参阅出现错误时使用 JAX-WS 跟踪 XML 请求/响应的问题。
回答by TriMix
// This solution provides a way programatically add a handler to the web service clien w/o the XML config
// 此解决方案提供了一种以编程方式向 Web 服务客户端添加处理程序的方法,无需 XML 配置
// See full doc here: http://docs.oracle.com/cd/E17904_01//web.1111/e13734/handlers.htm#i222476
// 在此处查看完整文档:http: //docs.oracle.com/cd/E17904_01//web.1111/e13734/handlers.htm#i222476
// Create new class that implements SOAPHandler
// 创建实现 SOAPHandler 的新类
public class LogMessageHandler implements SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
return Collections.EMPTY_SET;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
SOAPMessage msg = context.getMessage(); //Line 1
try {
msg.writeTo(System.out); //Line 3
} catch (Exception ex) {
Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
@Override
public void close(MessageContext context) {
}
}
// Programatically add your LogMessageHandler
// 以编程方式添加您的 LogMessageHandler
com.csd.Service service = null;
URL url = new URL("https://service.demo.com/ResService.svc?wsdl");
service = new com.csd.Service(url);
com.csd.IService port = service.getBasicHttpBindingIService();
BindingProvider bindingProvider = (BindingProvider)port;
Binding binding = bindingProvider.getBinding();
List<Handler> handlerChain = binding.getHandlerChain();
handlerChain.add(new LogMessageHandler());
binding.setHandlerChain(handlerChain);
回答by jozh
In runtimeyou could simply execute
在运行时你可以简单地执行
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump = true
as dumpis a public var defined in the class as follows
因为转储是类中定义的公共变量,如下所示
public static boolean dump;
回答by Alex
I am posting a new answer, as I do not have enough reputation to comment on the one provided by Antonio(see: https://stackoverflow.com/a/1957777).
我发布了一个新答案,因为我没有足够的声誉来评论Antonio提供的答案(请参阅:https: //stackoverflow.com/a/1957777)。
In case you want the SOAP message to be printed in a file (e.g. via Log4j), you may use:
如果您希望将 SOAP 消息打印在文件中(例如通过 Log4j),您可以使用:
OutputStream os = new ByteArrayOutputStream();
javax.xml.soap.SOAPMessage soapMsg = context.getMessage();
soapMsg.writeTo(os);
Logger LOG = Logger.getLogger(SOAPLoggingHandler.class); // Assuming SOAPLoggingHandler is the class name
LOG.info(os.toString());
Please note that under certain circumstances, the method call writeTo() may not behave as expected (see: https://community.oracle.com/thread/1123104?tstart=0or https://www.java.net/node/691073), therefore the following code will do the trick:
请注意,在某些情况下,方法调用 writeTo() 可能不会按预期运行(请参阅:https://community.oracle.com/thread/1123104?tstart =0或https://www.java.net/node /691073),因此以下代码将起作用:
javax.xml.soap.SOAPMessage soapMsg = context.getMessage();
com.sun.xml.ws.api.message.Message msg = new com.sun.xml.ws.message.saaj.SAAJMessage(soapMsg);
com.sun.xml.ws.api.message.Packet packet = new com.sun.xml.ws.api.message.Packet(msg);
Logger LOG = Logger.getLogger(SOAPLoggingHandler.class); // Assuming SOAPLoggingHandler is the class name
LOG.info(packet.toString());