我正在使用spring soap实现开发一个web服务,因此我的服务类使用@Endpoint注释进行注释。现在,我想将SPRING AOP用于我已经实现的应用程序日志记录。但是,正如我已经注意到的那样,直到我从切入点表达式中执行我的服务类,在调用我的webservice时,我得不到端点映射发现的异常。当我从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错误。
答案 0 :(得分:2)
@Tarun是对的,不过我也发现有必要延迟AppConfig config
bean的初始化。
因为(@hudi)示例中的CustomValidatingInterceptor
bean是EndpointInterceptor
,所以在Spring初始化序列的早期需要它。这意味着它在Aop编织config
bean之前已经实例化了。请注意原始问题中如何EndpointInterceptor
。
避免这种情况的一种方法是使用ObjectFactory
。这可以从一开始就接通,但是允许Spring延迟config
bean的实际实例化,直到拦截器和Aop代理都被很好地初始化为止。
在your question上有一个这样的例子。这次测试来自SoapUI。
答案 1 :(得分:1)
以下是您分享的代码
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()));
它工作正常
答案 2 :(得分:0)
尝试配置PayloadLoggingInterceptor
查看&#34; 5.5.2.1部分。 PayloadLoggingInterceptor和SoapEnvelopeLoggingInterceptor&#34;在Spring Reference Docs
中