首页 > 解决方案 > LoggingAspect - WebServiceTemplate.marshalSendAndReceive

问题描述

我正在尝试在调用 marshalSendAndReceive 时记录 Web 服务操作。这样我就可以记录任何使用 marshalSendAndReceive 的 Web 服务调用,如下所示。但不知何故 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);
    }

标签: aopspring-aopaspect

解决方案


Spring AOP 只能建议 Spring 容器管理的 bean。

从共享的代码来看,WebServiceTemplate建议的目标实例不是 Spring bean。

public Object callWebService(String url, Object request) {
    return getWebServiceTemplate().marshalSendAndReceive(url, request);
}

WebServiceGatewaySupport.getWebServiceTemplate()方法是从那里获取WebServiceTemplate实例的。默认逻辑是构造一个新的类实例WebServiceTemplate

基于参考文档 WebServiceTemplateBuilder可以用来创建一个WebServiceTemplatebean。

然后可以使用WebServiceGatewaySupport.setWebServiceTempate()来设置 bean。这样做时请阅读注释

或者,您可以建议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);
    }

推荐阅读