记录方面 - WebServiceTemplate.marshalSendAndReceive

LoggingAspect - WebServiceTemplate.marshalSendAndReceive

我正在尝试在调用 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() method is from where the WebServiceTemplate instance is obtained . The default logic is to construct a new instanceWebServiceTemplate class。

基于 reference documentation WebServiceTemplateBuilder 可用于创建 WebServiceTemplate bean。

WebServiceGatewaySupport.setWebServiceTempate() can then be used to set the bean. Do read on the 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);
    }