【问题标题】:Spring SOAP webservice endpoint with Spring AOP带有 Spring AOP 的 Spring SOAP Web 服务端点
【发布时间】:2015-11-03 05:53:16
【问题描述】:

我正在使用 Spring Soap 实现开发 Web 服务,因此我的服务类使用 @Endpoint 注释进行了注释。现在,我想将 SPRING AOP 用于我已经实现的应用程序日志记录。但是,正如我所注意到的,在我从切入点表达式中排除我的服务类之前,当我的 web 服务被调用时,我没有发现端点映射异常。当我将服务类排除在 AOP 的范围之外时,一切又正常了。对此有任何想法吗?

更新:

我的记录器类

package com.cps.arch.logging;

@Component
@Aspect
public class LoggerAspect {

    private static final Logger logger = LoggerFactory.getLogger("Centralized Payment System");

    @Before("(execution(* com.cps..*.*(..)) and not execution(* com.cps.service..*.*(..)))")
    public void logBefore(JoinPoint joinPoint) {

        logger.info("Execution Start : "+"Class: "+joinPoint.getTarget().getClass().getName()+
                "Method: "+joinPoint.getSignature().getName());
    }

}

我的服务端点:

package com.cps.service.impl;

@Endpoint
public class EndpointIntegrationServiceImpl  implements EndpointIntegrationService
{
    private static final String NAMESPACE_URI = "http://www.example.com/cps/model";

    @Autowired
    public MYBO myBO ;

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "SaveDataRequest")
    public void saveData(@RequestPayload
            SaveDataRequest data) {
        //business layer invocation
    }
}

我的 WS 配置

@EnableWs
@Configuration
@ComponentScan(basePackages={"com.cps"})
public class WebServiceConfig extends WsConfigurerAdapter
{

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    @Bean(name = "MyWsdl")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema schema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("MyPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://www.example.com/micro/payment/PaymentManagement");
        wsdl11Definition.setSchema(reconciliationSchema);
        return wsdl11Definition;
    }

    @Bean
    public XsdSchema schema() {
        return new SimpleXsdSchema(new ClassPathResource("XSD/MySchema.xsd"));
    }

    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        interceptors.add(validationInterceptor());
    }

    @Bean
    ValidationInterceptor validationInterceptor() {
            final ValidationInterceptor payloadValidatingInterceptor = new ValidationInterceptor();
            payloadValidatingInterceptor.setSchema(new ClassPathResource(
                    "XSD/MySchema.xsd"));
            return payloadValidatingInterceptor;
        }
}

抱歉,我不得不更改一些变量/类名称以遵守公司政策。 如您所见,我必须将“不执行”部分放在 AOP 中以使我的 Web 服务正常工作。如果我删除该部分,我会收到 404 错误。

【问题讨论】:

  • 能否请您展示您描述的两种情况的代码示例?
  • @Zergleb:请查看我的代码更新

标签: spring spring-boot spring-aop spring-ws


【解决方案1】:

@Tarun 是对的,虽然我也发现有必要延迟 AppConfig config bean 的初始化。

因为(@hudi's)示例中的CustomValidatingInterceptor bean 是EndpointInterceptor,所以在Spring 初始化序列的早期就需要它。这意味着它在针对config bean 的Aop 编织生效之前被实例化。请注意这里的原始问题中还有一个EndpointInterceptor

避免这种情况的一种方法是使用ObjectFactory。这可以从一开始就进行连接,但允许 Spring 延迟 config bean 的实际实例化,直到拦截器和 Aop 代理都被很好地初始化之后。

your question 上有一个例子。这在 SoapUI 中测试得很好。

【讨论】:

  • 谢谢很多人。你救了我的周末。赏金在 6 小时内是你的 :)
【解决方案2】:

所以下面是你分享的代码

package org.example;

import java.util.List;

import org.aspect.PersistentAspect;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;

import javax.annotation.PostConstruct;

@Configuration
@EnableWs
public class WsConfig extends WsConfigurerAdapter {

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        final MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/v1/*");
    }

    @Bean
    public XsdSchema schema() {
        return new SimpleXsdSchema(new ClassPathResource("country.xsd"));
    }

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        String[] jaxbContext = new String[] { "io.spring.guides.gs_producing_web_service" };
        marshaller.setContextPaths(jaxbContext);
        return marshaller;
    }

    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        // aop not working
        //interceptors.add(new CustomValidatingInterceptor(schema(), config()));
        System.out.println("Loading addInterceptors");
        interceptors.add(new CustomValidatingInterceptor(schema(), null));
    }

    @Bean
    public AppConfig config() {
        System.out.println("Loading config Bean");

        return new AppConfig();
    }

    @PostConstruct
    @Bean
    public PersistentAspect persistentAspect() {
        System.out.println("Loading persistentAspect Bean");
        PersistentAspect persistentAspect = new PersistentAspect();

        return persistentAspect;
    }

    @Bean
    public Object testAop(AppConfig config) {
        System.out.println("is config aop proxy: " + AopUtils.isAopProxy(config));

        return config;
    }
}

你提到它不适用于

interceptors.add(new CustomValidatingInterceptor(schema(), config()));

但适用于

interceptors.add(new CustomValidatingInterceptor(schema(), null));

当您手动调用config 时的问题,bean 是由您而不是由 Spring 启动的,它会以某种方式干扰。您不应该使用 bean 方法 config() 来启动类,而是使用类目录

interceptors.add(new CustomValidatingInterceptor(schema(), new AppConfig()));

而且效果很好

【讨论】:

    【解决方案3】:

    尝试配置PayloadLoggingInterceptor

    查看Spring Reference Docs 中的“5.5.2.1. PayloadLoggingInterceptor 和 SoapEnvelopeLoggingInterceptor”部分

    【讨论】:

    • 我在 Spring Boot 中使用带注释的配置。这只是春天
    • Spring 的一大优点是“如果可以用 XML 配置,就可以用代码配置”。
    • 是的,但不是那么容易,因为在春季靴子里有很多魔法。当春天有东西工作时,spring boot 只是删除 aop 代理而不发出警告,就像我更新的问题一样:stackoverflow.com/questions/50072312/…
    猜你喜欢
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多