• Soap从入门到实战


    Soap从入门到实战

    参考文章:https://howtodoinjava.com/spring-boot/spring-soap-client-webservicetemplate/

    使用的技术:springboot + jaxb

    一.soap是什么

    网上是这样解释的:

    SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。

    我的理解是:

    • 1.他是一种网络传输协议
    • 2.他的基础是http
    • 3.他传输内容不再是常用的文本而是xml

    二.soap和http的差别

    • 1.soap传输内容的是xml,http传输的内容是文本
    • 2.soap的wsdl文件可以暴露访问对象的接口,调用者可以详细的看到访问对象的结构。http只能传输文本没有描述信息,前端如果需要接口信息需要后端使用第三方插件或者自己书写。

    三.Wsdl

    wsdl是Web Sercivice Descripe Language 的简称,也就是说他是描述Web服务的语言。描述的内容有服务的路由,方法名,返回值等等。

    四.Wsdl基本结构

    <?xml version="1.0"?>
    <soap:Envelope
    xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
    soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
    
    <soap:Header>
      ...
      ...
    </soap:Header>
    
    <soap:Body>
      ...
      ...
      <soap:Fault>
        ...
        ...
      </soap:Fault>
    </soap:Body>
    
    </soap:Envelope>
    

    Envelope是强制使用的,我认为是一种引用的约束吧,强调我们的xml内容定义为soap消息

    五.soap实列

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.definesys.com/xml/employee"
               targetNamespace="http://www.definesys.com/xml/employee" elementFormDefault="qualified">
        <xs:element name="EmployeeDetailRequest">
            <xs:complexType>
                <xs:sequence>
                   <xs:element name="Employee" type="tns:Employee"></xs:element>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    
        <xs:element name="EmployeeDetailResponse">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="Employee" type="tns:Employee"></xs:element>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    
        <xs:complexType name="Employee">
            <xs:sequence>
                <xs:element name="code" type="xs:string"></xs:element>
                <xs:element name="name" type="xs:string"></xs:element>
                <xs:element name="email" type="xs:string"></xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:schema>
    

    namespace:http://www.definesys.com/xml/employee 自己取的

    targetNamespace="http://www.definesys.com/xml/employee" 自己定义的

    EmployeeDetailRequest:访问的入口,其中的内容是访问时需要的参数

    EmployeeDetailResponse:返回的出口,其中的内容是返回时返回的参数

    六.使用Springboot实战

    1.建立一个Web Service

    ​ File-------> New------->Project-------->Spring Initializer ------>web,web service

    2.导入jaxb依赖生成pojo等对象

    ​ 1.向pom中添加如下内容

     <!--插件-->
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>jaxb2-maven-plugin</artifactId>
                    <version>1.6</version>
                    <executions>
                        <execution>
                            <id>xjc</id>
                            <goals>
                                <goal>xjc</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
                        <!--<schemaFiles>employee.xsd</schemaFiles>-->
                        <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                        <packageName>com.example.webservice.entity</packageName>
                        <clearOutputDir>false</clearOutputDir>
                    </configuration>
                </plugin>
    

    ${project.basedir}/src/main/java: 定义输出文件的根目录

    com.example.webservice.entity :生成pojo的包名称

    false是否清空包目录

    生成的pojo如下:

    Employee:真实的普通java对象

    EmployeeDetailRequest: 封装了Emploee可以将请求中的soap对象解析成普通的Employee对象

    EmployeeDetaiResponse: 将普通的Employee对象封装成Soap对象

    package-info.java:绑定输出对象的命名空间

    3.相关注释的解释

    @XmlAccessorType(XmlAccessType.FIELD)
    

    定义类级别,将类的字段都写到xml中

    @XmlType(name = "Employee", propOrder = {    "code",    "name",    "email"})
    

    类定义级别,定义字段写到xml中的顺序

    @XmlElement(required = true)
    

    字段定义级别,将字段写入到xml中

    @XmlRootElement(name = "EmployeeDetailRequest")
    

    类定义级别,name指的是映射到xml时的名称

    4.写一个配置文件来生成wsdl

    package com.example.webservice.config;
    
    import org.springframework.beans.factory.parsing.DefaultsDefinition;
    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.ws.config.annotation.EnableWs;
    import org.springframework.ws.config.annotation.WsConfigurerAdapter;
    import org.springframework.ws.transport.http.MessageDispatcherServlet;
    import org.springframework.ws.wsdl.WsdlDefinition;
    import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
    import org.springframework.xml.xsd.SimpleXsdSchema;
    import org.springframework.xml.xsd.XsdSchema;
    
    @EnableWs
    @Configuration
    public class WebServiceConfig extends WsConfigurerAdapter {
        @Bean
        public ServletRegistrationBean messageDispathcherServlet(ApplicationContext applicationContext){
            MessageDispatcherServlet servlet=new MessageDispatcherServlet();
            servlet.setApplicationContext(applicationContext);
            servlet.setTransformWsdlLocations(true);
            return  new ServletRegistrationBean(servlet,"/cms/*");
        }
    
        @Bean(name="employee")
        public WsdlDefinition defaultWsdl11Defination(XsdSchema employeeSchema){
            DefaultWsdl11Definition wsdl=new DefaultWsdl11Definition();
            wsdl.setPortTypeName("EmployeePort");
            wsdl.setLocationUri("/cms/employee-detail");
            wsdl.setTargetNamespace("http://www.definesys.com/xml/employee");
            wsdl.setSchema(employeeSchema);
            return wsdl;
        }
    
        @Bean
        public XsdSchema employeeSchema(){
            return new SimpleXsdSchema(new ClassPathResource("employee.xsd"));
        }
    
    }
    
    

    messageDispathcherServlet:方法中指定我们项目访问的路径的根路径

    defaultWsdl11Defination:将我们书写的不完整的xsd文件书写成一个完成的wsdl并返回这个wsdl文件,在其中 添加了PortTypeName(似乎没什么用,l类似于端口号),LocationUri(路径),TargetNamespace(没什么大用)

    employeeSchema:返回我们自己写的xsd文件

    @bean:将我们的wsdl对象注入到spring容器 其中name是我们url访问的路径,因此我访问的employee.wsdl的路径是http://localhost:9999/cms/employee.wsdl

    5.书写我们的终端

    package com.example.webservice.controller;
    
    import com.example.webservice.entity.Employee;
    import com.example.webservice.entity.EmployeeDetailRequest;
    import com.example.webservice.entity.EmployeeDetailResponse;
    import org.springframework.ws.server.endpoint.annotation.Endpoint;
    import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
    import org.springframework.ws.server.endpoint.annotation.RequestPayload;
    import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
    
    @Endpoint
    public class EmploySoapController {
        private static final  String NAMESPACE_URI="http://www.definesys.com/xml/employee";
        @PayloadRoot(namespace = NAMESPACE_URI,localPart = "EmployeeDetailRequest")
        @ResponsePayload
        public EmployeeDetailResponse getEmployee1(@RequestPayload EmployeeDetailRequest request){
            EmployeeDetailResponse response=new EmployeeDetailResponse();
            Employee employee=new Employee();
            employee.setCode(2);
            employee.setName(2);
            employee.setEmail(2);
            response.setEmployee(employee);
            return  response;
        }
    
    }
    
    

    @PayloadRoot:namespace 指定我们的命名空间,客户端和服务端需要保持一致。localPart:在wsdl中访问的接口名,需要和wsdl中接口的名称一致,客户端访问的localPart也必须和wsdl中的接口一致。

    @ResponsePayload 说明输出的是一个soap消息,和@ResponseBody有点类似

    @RequesPayLoad 说明输入的是一个soap消息 和RequestBody类似

    6.测试

    1.下载soapui并安装

    2.新建一个soap项目

    3.添加一个wsdl文件

    4.输入wsdl的路径,我的是下图路径,如果报错可以去浏览器看看能不能打开,不能就检查路径是否正确

    http://localhost:9999/cms/employee.wsdl。没有改端口的朋友默认是8080

    5.在request中输入内容,输出就是相应逻辑的输出

    输出结果:

    6.客户端访问:url填写wsdl的路径即可,localpart填写:相应的访问接口的localPart即可

  • 相关阅读:
    LocalDate、LocalTime、LocalDateTime示例
    Instant时间戳示例
    Mybatis面试题
    SpringMVC面试题
    Spring面试题
    redis面试题
    计算机网络面试题
    java集合面试题
    java基础面试题
    MySQL面试题汇总
  • 原文地址:https://www.cnblogs.com/c-lover/p/12092829.html
Copyright © 2020-2023  润新知