我需要在 CommonLogFormat
(参见 http://en.wikipedia.org/wiki/Common_Log_Format)中记录的所有 SOAP 请求,加上持续时间(处理请求所花费的时间)。
最好的方法是什么?看起来可以为 Spring WebServices 配置 log4j,但它会记录我感兴趣的所有值吗? http://pijava.wordpress.com/2009/12/04/spring-webservice-soap-requestresponse-logging-with-log4j/
编辑:我们实际上使用的是 SLF4J
,而不是 Log4j
。此外,看起来可以通过配置 PayloadLoggingInterceptor 来做到这一点:http://static.springsource.org/spring-ws/site/reference/html/server.html#server-endpoint-interceptor
但我不确定日志消息会去哪里。我将该拦截器添加到我们的拦截器中,但没有看到任何日志消息。
对于 Spring Boot 项目,在 application.properties
中添加以下内容对我有用:
logging.level.org.springframework.web=DEBUG
logging.level.org.springframework.ws.client.MessageTracing.sent=DEBUG
logging.level.org.springframework.ws.server.MessageTracing.sent=DEBUG
logging.level.org.springframework.ws.client.MessageTracing.received=TRACE
logging.level.org.springframework.ws.server.MessageTracing.received=TRACE
您可以使用它来记录传入和传出 Web 服务调用的原始有效负载。我不确定如何记录 Web 服务通信花费的时间。
<!-- Spring Web Service Payload Logging-->
<logger name="org.springframework.ws.client.MessageTracing">
<level value="TRACE"/>
</logger>
<logger name="org.springframework.ws.server.MessageTracing">
<level value="TRACE"/>
</logger>
可在 http://static.springsource.org/spring-ws/site/reference/html/common.html#logging 找到更多详细信息
这对我有用。它记录发送的请求消息和收到的响应。您可以计算出从日志中花费的总时间。
log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE
log4j.logger.org.springframework.ws.client.MessageTracing.received=TRACE
如果您有自己的日志记录系统,则以下拦截器可以替代记录 SOAP 消息。
setInterceptors(new ClientInterceptor[]{new ClientInterceptor() {
@Override
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
System.out.println("### SOAP RESPONSE ###");
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
messageContext.getResponse().writeTo(buffer);
String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
System.out.println(payload);
} catch (IOException e) {
throw new WebServiceClientException("Can not write the SOAP response into the out stream", e) {
private static final long serialVersionUID = -7118480620416458069L;
};
}
return true;
}
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
System.out.println("### SOAP REQUEST ###");
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
messageContext.getRequest().writeTo(buffer);
String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
System.out.println(payload);
} catch (IOException e) {
throw new WebServiceClientException("Can not write the SOAP request into the out stream", e) {
private static final long serialVersionUID = -7118480620416458069L;
};
}
return true;
}
@Override
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
System.out.println("### SOAP FAULT ###");
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
messageContext.getResponse().writeTo(buffer);
String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
System.out.println(payload);
} catch (IOException e) {
throw new WebServiceClientException("Can not write the SOAP fault into the out stream", e) {
private static final long serialVersionUID = 3538336091916808141L;
};
}
return true;
}
}});
在每个句柄方法中,您都可以轻松地使用 payload
来获取原始肥皂消息。
org.springframework.ws.client.core.support.WebServiceGatewaySupport#setInterceptors
,实现的接口是 org.springframework.ws.client.support.interceptor.ClientInterceptor
,您还需要为此实现一个空的 afterCompletion
方法。
首先,SLF4J 只是一个简单的门面。这意味着您仍然需要一个日志框架(例如 java.util.logging、logback、log4j)。
其次,Spring-ws 使用 Commons Logging 接口,它是另一个类似 SLF4J 的简单外观。
最后,您可以使用以下设置来启用 Spring-ws 消息记录功能。
log4j.logger.org.springframework.ws.client.MessageTracing.sent=DEBUG
log4j.logger.org.springframework.ws.client.MessageTracing.received=TRACE
log4j.logger.org.springframework.ws.server.MessageTracing.sent=DEBUG
log4j.logger.org.springframework.ws.server.MessageTracing.received=TRACE
在 log4j.properties
文件中包含以下内容...
记录所有服务器端消息:log4j.logger.org.springframework.ws.server.MessageTracing=DEBUG 记录所有客户端消息:log4j.logger.org.springframework.ws.client.MessageTracing=TRACE
在 DEBUG
级别 - 仅记录有效负载根元素
在 TRACE
级别 - 记录整个消息内容
最后,要仅记录发送或接收的消息,请在配置末尾使用 .sent
或 .received
。
例如:log4j.logger.org.springframework.ws.server.MessageTracing.received=DEBUG
记录客户端收到的消息负载根元素返回:
DEBUG WebServiceMessageReceiverHandlerAdapter:114 - Accepting incoming [org.springframework.ws.transport.http.HttpServletConnection@51ad62d9] to [http://localhost:8080/mock-platform/services]
更多info
在 web.xml 中向 spring ws 添加一个 servlet 过滤器(与 org.springframework.web.servlet.DispatcherServlet 一起移动)
您可以在此处找到过滤器http://www.wetfeetblog.com/servlet-filer-to-log-request-and-response-details-and-payload/431
在过滤器内,您可以根据需要记录
. . .
package com.example.Soap;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.context.MessageContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class LoggingVonfig implements ClientInterceptor {
@Override
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
System.out.println("### SOAP RESPONSE ###");
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
messageContext.getResponse().writeTo(buffer);
String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
System.out.println(payload);
} catch (IOException e) {
throw new WebServiceClientException("Can not write the SOAP response into the out stream", e) {
private static final long serialVersionUID = -7118480620416458069L;
};
}
return true;
}
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
System.out.println("### SOAP REQUEST ###");
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
messageContext.getRequest().writeTo(buffer);
String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
System.out.println(payload);
} catch (IOException e) {
throw new WebServiceClientException("Can not write the SOAP request into the out stream", e) {
private static final long serialVersionUID = -7118480620416458069L;
};
}
return true;
}
@Override
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
System.out.println("### SOAP FAULT ###");
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
messageContext.getResponse().writeTo(buffer);
String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
System.out.println(payload);
} catch (IOException e) {
throw new WebServiceClientException("Can not write the SOAP fault into the out stream", e) {
private static final long serialVersionUID = 3538336091916808141L;
};
}
return true;
}
@Override
public void afterCompletion(MessageContext messageContext, Exception e) throws WebServiceClientException {
}
}
. . .
This is logging Configuration class
. . .
package com.example.Soap;
import com.example.Soap.com.example.Soap.Add;
import com.example.Soap.com.example.Soap.AddResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.client.core.SoapActionCallback;
public class CalculatorClient extends WebServiceGatewaySupport {
private static Logger log = LoggerFactory.getLogger(CalculatorClient.class);
public com.example.Soap.com.example.Soap.AddResponse getaddition(com.example.Soap.com.example.Soap.Add addrequest){
com.example.Soap.com.example.Soap.Add add = new com.example.Soap.com.example.Soap.Add();
add.setIntB(addrequest.getIntB());
add.setIntA(addrequest.getIntA());
log.info("----------------------------------------------"+"Inbound Request"+"-----------------------");
com.example.Soap.com.example.Soap.AddResponse addResponse = (com.example.Soap.com.example.Soap.AddResponse) getWebServiceTemplate().marshalSendAndReceive("http://www.dneonline.com/calculator.asmx?wsdl",add,new SoapActionCallback("http://tempuri.org/Add"));
return addResponse;
}
public com.example.Soap.com.example.Soap.SubtractResponse getSubtract(com.example.Soap.com.example.Soap.Subtract subreq){
com.example.Soap.com.example.Soap.Subtract subtract=new com.example.Soap.com.example.Soap.Subtract();
subtract.setIntA(subreq.getIntA());
subtract.setIntB(subreq.getIntB());
com.example.Soap.com.example.Soap.SubtractResponse subtractResponse=(com.example.Soap.com.example.Soap.SubtractResponse) getWebServiceTemplate().marshalSendAndReceive("http://www.dneonline.com/calculator.asmx?wsdl",subtract,new SoapActionCallback("http://tempuri.org/Subtract"));
return subtractResponse;
}
public com.example.Soap.com.example.Soap.MultiplyResponse getMultiply(com.example.Soap.com.example.Soap.Multiply multiply)
{
com.example.Soap.com.example.Soap.Multiply multiply1=new com.example.Soap.com.example.Soap.Multiply();
multiply1.setIntA(multiply.getIntA());
multiply1.setIntB(multiply.getIntB());
com.example.Soap.com.example.Soap.MultiplyResponse multiplyResponse=(com.example.Soap.com.example.Soap.MultiplyResponse) getWebServiceTemplate().marshalSendAndReceive("http://www.dneonline.com/calculator.asmx?wsdl",multiply1,new SoapActionCallback("http://tempuri.org/Multiply"));
return multiplyResponse;
}
public com.example.Soap.com.example.Soap.DivideResponse getDivide(com.example.Soap.com.example.Soap.Divide divide){
com.example.Soap.com.example.Soap.Divide divide1=new com.example.Soap.com.example.Soap.Divide();
divide1.setIntA(divide.getIntA());
divide1.setIntB(divide.getIntB());
com.example.Soap.com.example.Soap.DivideResponse divideResponse=(com.example.Soap.com.example.Soap.DivideResponse) getWebServiceTemplate().marshalSendAndReceive("http://www.dneonline.com/calculator.asmx?wsdl",divide1,new SoapActionCallback("http://tempuri.org/Divide"));
return divideResponse;
}
public void MySoapClient() {
this.setInterceptors(new ClientInterceptor[] { new LoggingVonfig() });
}
}
. . .
This is my client class
. . .
package com.example.Soap;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
@Configuration
public class CalculatorConfig {
@Bean
public Jaxb2Marshaller marshaller(){
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
// jaxb2Marshaller.setPackagesToScan("com.example.Soap.com.example.Soap");
jaxb2Marshaller.setContextPath("com.example.Soap.com.example.Soap"); // this will serilaize and unserialize it
return jaxb2Marshaller;
}
@Bean
public CalculatorClient calculatorClient(Jaxb2Marshaller jaxb2Marshaller){
WebServiceTemplate wsTemplate = new WebServiceTemplate();
CalculatorClient calculatorClient = new CalculatorClient();
calculatorClient.setDefaultUri("http://www.dneonline.com");
calculatorClient.setMarshaller(jaxb2Marshaller);
calculatorClient.setUnmarshaller(jaxb2Marshaller);
return calculatorClient;
}
}
. . .
configuration file
. . .
package com.example.Soap;
import com.example.Soap.com.example.Soap.Add;
import com.example.Soap.com.example.Soap.AddResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class SoapApplication {
@Autowired
private CalculatorClient calculatorClient;
@PostMapping(value = "/add")
public com.example.Soap.com.example.Soap.AddResponse addelements(@RequestBody com.example.Soap.com.example.Soap.Add add){
return calculatorClient.getaddition(add);
}
@PostMapping(value = "/subtract")
public com.example.Soap.com.example.Soap.SubtractResponse addelements(@RequestBody com.example.Soap.com.example.Soap.Subtract subreq){
return calculatorClient.getSubtract(subreq);
}
@PostMapping(value = "/multiply")
public com.example.Soap.com.example.Soap.MultiplyResponse addelements(@RequestBody com.example.Soap.com.example.Soap.Multiply multiply){
return calculatorClient.getMultiply(multiply);
}
@PostMapping(value = "/divide")
public com.example.Soap.com.example.Soap.DivideResponse addelements(@RequestBody com.example.Soap.com.example.Soap.Divide divide){
return calculatorClient.getDivide(divide);
}
public static void main(String[] args) {
SpringApplication.run(SoapApplication.class, args);
}
}
. . .
这些是我的课程,但我仍然无法在控制台中记录所有请求和响应。我没有得到我做错的地方。我也实现了客户端配置。