Spring Boot WebServices 实战解析:@Endpoint vs @WebService

前言
Web Services 是特殊的网络服务,它允许位于不同地点的计算机程序通过互联网交流和共享数据。这些服务可以通过多种方式实现,其中包括使用SOAP协议和遵循REST原则。
在SOAP的实现中,Spring Web Services(Spring WS)和Java API for XML Web Services(JAX-WS)是两种主要的技术选择。Spring WS 是专为简化SOAP Web Services的开发而设计的,提供了一种创建文档驱动、基于SOAP的服务的方式,特别适合需要深度集成和复杂配置的企业级应用。相比之下,JAX-WS 是遵循WS-*标准的更为基础和轻量级的Java API,适用于需要标准Java支持且配置较少的场景。
本文主要展示这两种技术在Spring Boot环境中实现方式。
本文两种实现方式
@Endpoint 注解实现 SOAP Web Services
@WebService 注解实现 SOAP Web Services
版本
Java:8
Spring Boot:2.3.12.RELEASE
@Endpoint

@Endpoint注解来自Spring Web Services(Spring WS)项目,它专门用于处理SOAP Web服务的开发。Spring WS 不依赖于企业Java的标准,而是建立在Spring框架的基础之上,提供更灵活的配置和更好的集成。

@Endpoint示例参考此篇文件:https://www.baeldung.com/spring-boot-soap-web-service。但有几个点需要改动。

图片
  1. Maven依赖。
    org.springframework.boot spring-boot-starter-web-services
    wsdl4j wsdl4j
  2. 在src/main/resources目录下创建一个名为 countries.xsd 的XSD文件(XML Schema Definition),用于定义SOAP消息的结构。这个Schema将作为生成Java类的基础,用于请求和响应的数据结构。


  3. 配置jaxb maven插件,将定义的 XSD 文件生成对应的 Java 类。
    org.codehaus.mojo jaxb2-maven-plugin 3.1.0 xjc xjc src/main/resources/countries.xsd src/main/java/endpoint false
    source路径自己定义,相对路径绝对路径都可以。
    控制台输入命令:
    mvn package
    则会生成对应的java类,拷贝到对应的目录下即可。
  4. 添加 SOAP Web 服务端点。
    @Component
    @Endpoint
    public class CountryEndpoint { private static final String NAMESPACE_URI = “http://www.baeldung.com/springsoap/gen”; @PayloadRoot(namespace = NAMESPACE_URI, localPart = “getCountryRequest”)
    @ResponsePayload
    public JAXBElement getCountry(@RequestPayload JAXBElement request) {
    GetCountryResponse response = new GetCountryResponse();
    Country country = new Country();
    country.setCapital(“12”);
    country.setName(request.getValue().getName());
    response.setCountry(country);
    return new JAXBElement<>(new QName(NAMESPACE_URI, GetCountryResponse.class.getSimpleName()), GetCountryResponse.class, response);
    }

}
注解含义:
@Endpoint:将类作为 Web 服务端点注册到 Spring WS。(端点可理解为处理特定类型的请求处理器)
@PayloadRoot:标记具体处理SOAP请求的方法。根据命名空间和 localPart 属性定义处理程序方法。
namespace:命名空间URI,用于标识特定的XML文档或元素集。
localPart:本地名称,指定在给定命名空间中的特定元素。
@ResponsePayload:处理将Java对象转换回SOAP消息的注解。
@RequestPayload:该注解将SOAP请求参数反序列化为java对象。
JAXBElement:相当于一个包装器,用来包含单个XML元素的信息。上述例子中创建JAXBElement是确保响应有正确的命令空间和本地名称。
namespace和localPart对应关系如下图:

  1. SOAP Web 服务配置 Bean。
    WebServiceConfig类主要目的是配置和发布一个基于 SOAP 协议的 Web 服务。
    @EnableWs //启用Spring Web Services的配置支持
    @Configuration
    public class WebServiceConfig extends WsConfigurerAdapter { @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
    //定义一个servlet,用于处理soap消息
    MessageDispatcherServlet servlet = new MessageDispatcherServlet();
    servlet.setApplicationContext(applicationContext);
    servlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean<>(servlet, “/ws/*”);
    } @Bean(name = “countries”)
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    //公开一个标准的WSDL 1.1文档
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName(“CountriesPort”);
    //定义服务的访问地址,即客户端访问Web服务的端点
    wsdl11Definition.setLocationUri(“/ws”);
    wsdl11Definition.setTargetNamespace(“http://www.baeldung.com/springsoap/gen”);
    //关联xsd文件
    wsdl11Definition.setSchema(countriesSchema);
    return wsdl11Definition;
    } @Bean
    public XsdSchema countriesSchema() {
    return new SimpleXsdSchema(new ClassPathResource(“countries.xsd”));
    }
    }
    应用启动成功后,打开url来验证wsdl文件是否成功发布:http://localhost:18889/ws/countries.wsdl。(我本地应用端口非8080)
    WSDL 文件如下:
<xs:element name="getCountryRequest">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="getCountryResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="country" type="tns:country"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:complexType name="country">
    <xs:sequence>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="population" type="xs:int"/>
        <xs:element name="capital" type="xs:string"/>
        <xs:element name="currency" type="tns:currency"/>
    </xs:sequence>
</xs:complexType>

<xs:simpleType name="currency">
    <xs:restriction base="xs:string">
        <xs:enumeration value="GBP"/>
        <xs:enumeration value="EUR"/>
        <xs:enumeration value="PLN"/>
    </xs:restriction>
</xs:simpleType>









文件内容:
types(类型):定义web服务之间传递的数据类型。
message(消息):定义web服务中用于通信的消息结构。
portType(端口类型):定义web服务接口,包含一组操作,每个操作定义了输入和输出得消息结构。
binding(绑定):定义web服务的通信协议和消息格式。
service(服务):定义web服务的实际访问地址。

  1. 用 postman 测试 SOAP 项目。

@WebService

@WebService注解来自JAX-WS(Java API for XML Web Services)标准,它是一个专门用于创建SOAP(Simple Object Access Protocol)Web服务的API。这种方法通常用于实现符合WS-标准的Web服务,并且是Java EE规范的一部分。

  1. Maven依赖。
    org.springframework.boot spring-boot-starter-web-services
    org.apache.cxf cxf-spring-boot-starter-jaxws 3.4.4
  2. 定义webservices接口。
    @WebService(name = “PersonnelInfo”,
    targetNamespace = “http://service.manage.com/”)
    public interface PersonnelInfoService { @WebMethod
    String syncPersonnelInfo(@WebParam(name = “xmlData”, targetNamespace = “http://service.manage.com/”) String jsonData);
    }
    @WebService:标记一个接口或类作为Web服务的服务端点。
    name:指定服务的名称。
    targetNamespace:定义了这个Web服务所使用的XML命名空间。
    @WebMethod 和 @WebParam 注解用于定义 Web 服务中的方法和参数。
  3. 定义webservices实现类。

//endpointInterface:服务接口全路径

@Slf4j
@Component
@WebService(name = “PersonnelInfo”,
targetNamespace = “http://service.manage.com/”,
endpointInterface = “com.manage.service.PersonnelInfoService”)
public class PersonnelInfoServiceImpl implements PersonnelInfoService {

@Override
public String syncPersonnelInfo(@WebParam(name = "xmlData", targetNamespace = "http://service.manage.com/") String xmlData) {
    String result = "success";
    log.info("三方信息调用入参:{}", xmlData);
}

}

  1. 发布webservices服务。
    @Configuration
    public class CxfConfig { @Autowired
    private Bus bus;
    @Autowired
    private PersonnelInfoService personnelInfoService; @Bean(name = “wsBean”)
    public ServletRegistrationBean dispatcherServlet() {
    //注册servlet,用于处理web服务请求
    ServletRegistrationBean wbsServlet = new ServletRegistrationBean(new CXFServlet(), “/ws/*”);
    return wbsServlet;
    } /**
    • JAX-WS
    • 站点服务
      **/
      @Bean
      public Endpoint endpoint() {
      //发布Web服务的类,将请求都交给personnelInfoService类处理
      EndpointImpl endpoint = new EndpointImpl(bus, personnelInfoService);
      //将当前端点发布到URL路径/data上
      endpoint.publish(“/data”);
      return endpoint;
      }

}

输入下面url检查程序发布是否正常:http://localhost:8080/ws/countries.wsdl

  1. 用 postman 测试 SOAP 项目。

总结

@Endpoint 和 @WebService 这两种方式都可以实现接收 XML 请求的需求。其中一个依赖于 JAX-WS 标准,更适合定制化和特殊需求的 Web 服务实现;另一个依赖于 JAX-WS 标准,适用于遵循规范和标准化的项目。具体可根据实际需求和开发栈来选择合适的实现方式。
参考资料
https://www.baeldung.com/spring-boot-soap-web-service

阅读原文


作者简介: 持续更新后端领域知识。欢迎关注微信公众号:阿飞技术

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/415030.html

联系我们
联系我们
分享本页
返回顶部