ami*_*que 5 java spring web-services jax-ws spring-boot
在我的基于 spring boot ws 的应用程序中,我按照契约优先的方法创建了一个 jax-ws 网络服务。Web 服务已启动,但我无法在我的 Web 服务中自动装配其他 bean。
我如何将 spring 中的 webservice 定义为 bean?
以下是我的 webservice impl 类:
@WebService(endpointInterface = "com.foo.bar.MyServicePortType")
@Service
public class MySoapService implements MyServicePortType {
@Autowired
private MyBean obj;
public Res method(final Req request) {
System.out.println("\n\n\nCALLING.......\n\n" + obj.toString()); //obj is null here
return new Res();
}
}
Run Code Online (Sandbox Code Playgroud)
MyServicePortType 由 maven 从 wsdl 文件生成
当我调用这个服务(通过 SoapUi)时,它给出了NullPointerException因为 MyBean 对象不是自动装配的。
由于我的应用程序是基于 Spring Boot 构建的,因此没有 xml 文件。目前我有sun-jaxws.xml带有端点配置的文件。如何在 Spring Boot 应用程序中进行以下配置
<wss:binding url="/hello">
<wss:service>
<ws:service bean="#helloWs"/>
</wss:service>
</wss:binding>
Run Code Online (Sandbox Code Playgroud)
以下是我的SpringBootServletInitializer课:
@Configuration
public class WebXml extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(WSApplication.class);
}
@Bean
public ServletRegistrationBean jaxws() {
final ServletRegistrationBean jaxws = new ServletRegistrationBean(new WSServlet(), "/jaxws");
return jaxws;
}
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new WSServletContextListener());
}
}
Run Code Online (Sandbox Code Playgroud)
扩展SpringBeanAutowiringSupport是从当前 spring 根 Web 应用程序上下文为 JAX-WS 端点类注入 bean 的推荐方法。然而,这不适用于spring boot,因为它在servlet 上下文初始化上有点不同。
SpringBootServletInitializer.startup()使用自定义ContextLoaderListener并且不会将创建的应用程序上下文传递给ContextLoader. 稍后当 JAX-WS 端点类的对象被初始化时,SpringBeanAutowiringSupport依赖于ContextLoader检索当前应用程序上下文,并且总是获取null.
public abstract class SpringBootServletInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootAppContext = createRootApplicationContext(
servletContext);
if (rootAppContext != null) {
servletContext.addListener(new ContextLoaderListener(rootAppContext) {
@Override
public void contextInitialized(ServletContextEvent event) {
// no-op because the application context is already initialized
}
});
}
......
}
}
Run Code Online (Sandbox Code Playgroud)
您可以注册一个 bean 来实现org.springframework.boot.context.embedded.ServletContextInitializer在startup().
@Configuration
public class WebApplicationContextLocator implements ServletContextInitializer {
private static WebApplicationContext webApplicationContext;
public static WebApplicationContext getCurrentWebApplicationContext() {
return webApplicationContext;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在 JAX-WS 端点类中实现自自动装配。
@WebService
public class ServiceImpl implements ServicePortType {
@Autowired
private FooBean bean;
public ServiceImpl() {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
WebApplicationContext currentContext = WebApplicationContextLocator.getCurrentWebApplicationContext();
bpp.setBeanFactory(currentContext.getAutowireCapableBeanFactory());
bpp.processInjection(this);
}
// alternative constructor to facilitate unit testing.
protected ServiceImpl(ApplicationContext context) {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(new DefaultListableBeanFactory(context));
bpp.processInjection(this);
}
}
Run Code Online (Sandbox Code Playgroud)
在单元测试中,您可以注入当前的 spring 应用程序上下文,并用它调用替代构造函数。
@Autowired
private ApplicationContext context;
private ServicePortType service;
@Before
public void setup() {
this.service = new ServiceImpl(this.context);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15640 次 |
| 最近记录: |