问题描述
我正在尝试在调用 marshalSendAndReceive 时记录 Web 服务操作。这样我就可以记录任何使用 marshalSendAndReceive 的网络服务调用,如下所示。但不知何故下面的 logWebserviceOperation 没有被调用。我的@Before .. 有什么问题吗?或者我错过了什么。
package com.julia;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletinitializer;
@SpringBootApplication
public class Application extends SpringBootServletinitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
package com.julia.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
import com.julia.service.soAPConnector;
import static com.julia.config.ApplicationConstants.CONTEXT_PATH_1; //contstants to set the Jaxb context path
import static com.julia.config.ApplicationConstants.CONTEXT_PATH_2;
import static com.julia.config.ApplicationConstants.CONTEXT_PATH_3;
@Configuration
@RefreshScope
public class ParserConfig {
@Value("${application.WSSessionTimeoutInMilliSec}")
private int timeout;
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(CONTEXT_PATH_1,CONTEXT_PATH_2,CONTEXT_PATH_3);
return marshaller;
}
@Bean
public SOAPConnector soapConnector(Jaxb2Marshaller marshaller) {
SOAPConnector client = new SOAPConnector();
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
messageSender.setConnectionTimeout(timeout);
client.setMessageSender(messageSender);
return client;
}
}
package com.julia.service;
import java.io.IOException;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpUrlConnection;
@Service
@RefreshScope
public class SOAPConnector extends WebServiceGatewaySupport {
private static final Logger LOGGER = LogManager.getLogger(SOAPConnector.class);
public Object callWebService(String url,Object request) {
return getwebservicetemplate().marshalSendAndReceive(url,request);
}
}
package com.julia.logging;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.sqlParameterValue;
import org.springframework.jdbc.core.namedparam.MapsqlParameterSource;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
private static final Logger LOGGER = LogManager.getLogger(LoggingAspect.class);
public LoggingAspect() {
}
@Before("execution(* org.springframework.ws.client.core.webservicetemplate.marshalSendAndReceive(..))")
public void logWebserviceOperation(JoinPoint jp) {
Object[] methodArgs = jp.getArgs();
String uri = methodArgs[0].toString();
String payload = String.valueOf(methodArgs[1]);
LOGGER.log("uri:" + uri);
LOGGER.log("payload :" + payload);
}
解决方法
Spring AOP 只能通知 Spring 容器管理的 bean。
从共享的代码来看,建议所针对的 WebServiceTemplate
实例不是 Spring bean。
public Object callWebService(String url,Object request) {
return getWebServiceTemplate().marshalSendAndReceive(url,request);
}
WebServiceGatewaySupport.getWebServiceTemplate() 方法是从哪里获得 WebServiceTemplate
实例。默认逻辑是构造一个 new instance 的 WebServiceTemplate
类。
基于 reference documentation WebServiceTemplateBuilder
可用于创建 WebServiceTemplate
bean。
WebServiceGatewaySupport.setWebServiceTempate() 然后可用于设置 bean。这样做时,请务必阅读 notes。
或者,您可以建议 SOAPConnector.callWebService(..)
应该为您提供相同的日志。
@Before("execution(* com.julia.service.SOAPConnector.callWebService(..)) && args(url,request)")
public void logWebserviceOperation(JoinPoint jp,String url,Object request) {
LOGGER.log("uri:" + url);
LOGGER.log("payload :" + request);
}