当前位置: 首页 > 面试题库 >

Spring Boot将JAX-WS Web服务注册为Bean

孔嘉茂
2023-03-14
问题内容

在基于春季启动ws的应用程序中,我遵循合同优先方法创建了一个jax-ws
Web服务。Web服务已启动,但是我无法自动将其他bean绑定到Webservice中。

我如何在春季将Web服务定义为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();
    }
}

MyServicePortType由Maven从wsdl文件生成

当我通过SoapUi调用此服务时,它会给出,NullPointerException因为MyBean对象未自动装配。

由于我的应用程序是基于Spring启动构建的,因此没有xml文件。目前,我有sun-jaxws.xml带有端点配置的文件。我如何在Spring
Boot应用程序中进行以下配置

<wss:binding url="/hello">
    <wss:service>
        <ws:service bean="#helloWs"/>
    </wss:service>
</wss:binding>

以下是我的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());
    }
}

问题答案:

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
                }
            });
        }
        ......
    }
}

解决方法

您可以注册一个实现org.springframework.boot.context.embedded.ServletContextInitializer了在期间检索应用程序上下文的bean
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);
    }
}

然后,您可以在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);
    }
}

单元测试

在单元测试中,您可以注入当前的spring应用程序上下文,并使用它调用替代构造函数。

@Autowired 
private ApplicationContext context;

private ServicePortType service;

@Before
public void setup() {
    this.service = new ServiceImpl(this.context);
}


 类似资料:
  • 在我的基于spring boot ws的应用程序中,我遵循契约优先的方法创建了一个jax-ws webservice。Web服务已启动,但我无法在WebService中调用其他bean。 由于我的应用程序是基于Spring boot构建的,所以没有xml文件。目前,我有文件和endpoint配置。如何在spring boot应用程序中进行以下配置 下面是我的类:

  • 要注册为Windows服务,首先以Administrator身份运行 cmd,然后执行以下命令: sc create gitea start= auto binPath= "\"C:\gitea\gitea.exe\" web --config \"C:\gitea\custom\conf\app.ini\"" 别忘了将 C:\gitea 替换成你的 Gitea 安装目录。 之后在控制面板打开

  • 在进行服务拆分之后,服务的数量会变得非常多,而每个服务又可能会有非常多的集群节点来提供服务,那么为保障系统的正常运行,必然需要有一个中心化的组件完成对各个服务的整合,即将分散于各处的服务进行汇总,汇总的信息可以是提供服务的组件名称、地址、数量等,每个组件拥有一个监听设备,当本组件内的某个服务的状态变化时报告至中心化的组件进行状态的更新。服务的调用方在请求某项服务时首先到中心化组件获取可提供该项服务

  • 本文向大家介绍SpringBoot的服务注册与发现示例,包括了SpringBoot的服务注册与发现示例的使用技巧和注意事项,需要的朋友参考一下 微服务 实践“微服务”自然要学习如何做服务注册与发现 基于SpringBoot来进行微服务的学习,自然选择了与之息息相关的SpringCloud;当然可以选择其他的技术进行,比如dubbo 也可以用zookeeper来实现服务注册与发现,至于zookeep

  • 问题内容: 我试图通过注释将无状态EJB注入到JAX-RS Web服务中。不幸的是,EJB是正义的,当我尝试使用它时我得到了。 我究竟做错了什么? 以下是有关我的机器的一些信息: Glassfish 3.1 Netbeans 6.9 RC 2 Java EE 6 你们能举个可行的例子吗? 问题答案: 我不确定这是否行得通。所以: 选项1:使用注入提供程序SPI 实现一个提供程序,它将执行查找并注入

  • 本文向大家介绍springboot 注册服务注册中心(zk)的两种方式详解,包括了springboot 注册服务注册中心(zk)的两种方式详解的使用技巧和注意事项,需要的朋友参考一下 在使用springboot进行开发的过程中,我们经常需要处理这样的场景:在服务启动的时候,需要向服务注册中心(例如zk)注册服务状态,以便当服务状态改变的时候,可以故障摘除和负载均衡。 我遇到过两种注册的途径: 1、