我可以同时使用 SOAP Webservices 和 Spring MVC 吗

问题描述 投票:0回答:3

我有一个 Spring MVC 项目。我写了一段类似的代码

@Controller
@RequestMapping("CallBack")
@WebService(name = "NotificationToCP", targetNamespace = "http://SubscriptionEngine.ibm.com")
public class CallbackController {

    @RequestMapping("")
    @ResponseBody
    @WebMethod(action = "notificationToCP")
    @RequestWrapper(localName = "notificationToCP", targetNamespace = "http://SubscriptionEngine.ibm.com", className = "in.co.mobiz.airtelVAS.model.NotificationToCP_Type")
    @ResponseWrapper(localName = "notificationToCPResponse", targetNamespace = "http://SubscriptionEngine.ibm.com", className = "in.co.mobiz.airtelVAS.model.NotificationToCPResponse")
    public NotificationToCPResponse index(
            @WebParam(name = "notificationRespDTO", targetNamespace = "") CPNotificationRespDTO notificationRespDTO) {
        return new NotificationToCPResponse();
    }
}

我可以一起使用Spring MVC + Webservices吗?我想要的只是一个接受 SOAP 请求并处理它的控制器。 url 必须是 /CallBack。作为一个新手,我仍然感到困惑。像上面这样的东西会起作用吗?否则我该如何让它继续下去。

java web-services spring
3个回答
5
投票

我不会将 Spring MVC 和 SOAP Web 服务 (JAX-WS) 混合在一起,因为它们有不同的用途。

更好的做法是将业务操作封装在服务类中,并使用 MVC 控制器和 JAX-WS 公开它。例如:

您好服务

@Service
public class HelloService {
    public String sayHello() {
        return "hello world";
    }
}

HelloController 通过自动装配注入了 HelloService 引用。这是标准 Spring MVC 控制器,它调用服务并将结果作为模型传递给视图(例如:hello.jsp 视图)

@Controller
@RequestMapping("/hello")
public class HelloController {
    @Autowired private HelloService helloService;

    @RequestMapping(method = RequestMethod.GET)
    public String get(Model model) {
        model.addAttribute("message", helloService.sayHello());
        return "hello";
    }
}

JAX-WS 端点也调用相同的服务。不同之处在于该服务作为 SOAP Web 服务公开

@WebService(serviceName="HelloService")
public class HelloServiceEndpoint {
    @Autowired private HelloService helloService;

    @WebMethod
    public String sayHello() {
        return helloService.sayHello();
    }
}

请注意,上面的 JAX-WS 风格的 Web 服务不能保证在所有 Spring 部署上自动工作,特别是部署在非 Java EE 环境 (tomcat) 上时。可能需要额外的设置。


0
投票

是的,您可能出于某些原因想要向现有 Spring MVC 应用程序添加 Web 服务端点。问题是您可能需要为每个路径设置不同的路径,这很好。

您将需要两个 servlet,一个用于处理 HTTP/MVC 的标准调度程序 servlet 和一个用于处理 SOAP 调用的 MessageDispatcherServlet。

配置可能很棘手。首先要明白,当您添加 Spring-ws 依赖项时,您将与 Spring MVC 存在依赖项不匹配的情况。您需要在 pom 中排除 Spring-web,如下所示:

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>2.2.1.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>

完成此操作后,您将需要添加两个 servlet,一个用于通过 Spring MVC 处理 Web 请求,另一个用于处理 SOAP。

我假设使用 Spring 4 进行 no-xml 配置,SpringBoot 也是可能的。

这是您将添加到 Web 初始化程序中的关键代码:

DispatcherServlet servlet = new DispatcherServlet();

// no explicit configuration reference here: everything is configured in the root container for simplicity
servlet.setContextConfigLocation("");

/* TMT From Java EE 6 API Docs:
 * Registers the given servlet instance with this ServletContext under the given servletName.
 * The registered servlet may be further configured via the returned ServletRegistration object. 
 */

ServletRegistration.Dynamic appServlet = servletContext.addServlet("appServlet", servlet);
appServlet.setLoadOnStartup(1);
appServlet.setAsyncSupported(true);

Set<String> mappingConflicts = appServlet.addMapping("/web/*");

MessageDispatcherServlet mds = new MessageDispatcherServlet();
mds.setTransformWsdlLocations(true);
mds.setApplicationContext(context);
mds.setTransformWsdlLocations(true);

ServletRegistration.Dynamic mdsServlet = servletContext.addServlet("mdsServlet", mds);
mdsServlet.addMapping("/wsep/*");
mdsServlet.setLoadOnStartup(2);
mdsServlet.setAsyncSupported(true);

这就是全部内容了。其余的配置是标准的东西,可以在许多示例中找到。

例如,您可以轻松地将 Spring MVC 和 Spring-WS 的 Spring IO 示例混合作为测试床。只需确保相应地设置

WebMvcConfigurerAdapter
WsConfigurerAdapter
即可。它们将是两个独立的类,分别用
@Configuration @EnableWebMvc
@EnableWs @Configuration
单独注释。它们必须与您的
@Endpoint
类一起添加到组件扫描中。

使用浏览器通过

/web/*
编译、运行和测试根上下文中的 MVC 内容,并通过导入 WSDL 并点击根中的
/wsep/*
使用 SoapUI 进行 SOAP 调用。每个 servlet 处理的每个路径。


0
投票

在看到 stackoverflow 中的所有建议后,我觉得我需要创建两个调度程序 servlet,一个用于 SOAP 端点,另一个用于 REST 端点,以便 SOAP 和 REST 端点可以构建到同一个项目中。但这里的关键点是调度程序 servlet 应该指向它自己的 URL 映射。我们可以将每个 servlet 配置为拥有自己的 URL 映射。 我正在使用 Spring Boot,下面的内容似乎适用于我的情况。我希望它可以帮助其他人。

第一步: 您可以禁用 Spring Boot 的自动配置调度程序 servlet,或者我们可以使用默认的自动配置调度程序来保持其原始行为。 经过多次组合测试后,我意识到将自动配置的调度程序保留其原始行为会更容易。

但是如果您有兴趣调整该调度程序 servlet,您可以执行以下操作:

  1. @SpringBootApplication(exclude = DispatcherServletAutoConfiguration.class) -> 在你的主类中。

  2. 在新班级,

    @配置 公共类 RestWebConfig {

     @Bean
     public DispatcherServlet dispatcherServlet() {
         DispatcherServlet dispatcherServlet = new DispatcherServlet();
         //dispatcherServlet.setThreadContextInheritable(true);
         //dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
         return dispatcherServlet;
     }       
     @Bean
     public ServletRegistrationBean dispatcherServletRegistration() {
         ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet());            
         registration.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
         return registration;
     }
     @Bean
     public DispatcherServletPath dispatcherServletPath() {
         return () -> "/rest";
     }
    

    }

第二步: 我尝试自定义 DispatcherServlet,使我的第二个 SOAP 调度程序 servlet 指向“/”,但我无法让它工作。 因此,我默认为原始行为,所有 REST 请求都将路由到 Spring Boot 的自动配置的 DispatcherServlet。 然后我创建了下面的 Message DispatcherServlet,它实际上构建在 DispatcherServlet 之上,具有不同的 URL 映射 - “/soap/”。

@EnableWs
@Configuration
public class WebConfig extends WsConfigurerAdapter{ 
    
    @Bean
    public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean<>(servlet, "/soap/*");
    }
    
    
    @Bean(name = "app")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchemaCollection appserviceSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("AppservicePort");
        wsdl11Definition.setLocationUri("/soap/appservice");
        wsdl11Definition.setTargetNamespace("http://xmlns.fedex.com/appservice");   
        wsdl11Definition.setSchemaCollection(appserviceSchema);
        return wsdl11Definition;
    }
    
    @Bean
    public XsdSchemaCollection appserviceSchema() {
        return new CommonsXsdSchemaCollection(new ClassPathResource("xsds/CommonServices.xsd"));
    }
}

有了以上配置,

  1. 我的所有 SOAP 请求都将通过自定义 messageDispatcherServlet 路由,然后发送到 SOAP 端点。 当然,我所有的 SOAP 端点都必须以 /soap/* 开头
  2. 所有 REST 请求都将通过默认的 DispatcherServlet 路由,然后发送到我的 REST 端点。 REST端点可以以除soap之外的任何内容开始
© www.soinside.com 2019 - 2024. All rights reserved.