zoukankan      html  css  js  c++  java
  • Spring Boot SOAP Webservice例子

    前言

    本文将学习如何利用Spring boot快速创建SOAP webservice服务;

    虽然目前REST和微服务越来越流行,但是SOAP在某些情况下,仍然有它的用武之地;

    在本篇 spring boot SOAP教程中,我们会专注于和Spring boot相关的配置,感受下在Spring Boot中,创建SOAP webservice是如何的简便、快速;

    本文将以一个"学生搜索"这个小功能作为示例,演示Spring Boot中SOAP webservice的创建过程;

    技术栈

    • JDK 1.8, Eclipse, Maven – 开发环境
    • Spring-boot – 基础开发框架
    • wsdl4j – 发布WSDL
    • SOAP-UI – 测试服务
    • JAXB maven plugin - 代码生成

    工程结构

    本工程的代码及文件目录结构如下
    file

    创建Spring Boot工程

    访问 SPRING INITIALIZR网站,添加Web Services依赖,输入maven的GAV 坐标,点击下载工程,下载完成后解压导入IDE即可;
    file
    修改pom.xml文件,添加Wsdl4j依赖:

    <dependency>
        <groupId>wsdl4j</groupId>
        <artifactId>wsdl4j</artifactId>
    </dependency>
    

    创建SOAP Domain模型并生成Java代码

    首先,我们需要给我们的服务创建domain(方法和参数),出于简便考虑,我将请求和响应放在了同一个XSD文件里,不过在实际应用开发的时候,通常需要放到多个XSD文件里;

    创建student.xsd文件,并放到我们工程的resources 目录下
    student.xsd

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.howtodoinjava.com/xml/school"
    targetNamespace="http://www.howtodoinjava.com/xml/school" elementFormDefault="qualified">
     
        <xs:element name="StudentDetailsRequest">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="name" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
     
        <xs:element name="StudentDetailsResponse">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="Student" type="tns:Student"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
     
        <xs:complexType name="Student">
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="standard" type="xs:int"/>
                <xs:element name="address" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
         
    </xs:schema>
    

    添加JAXB maven插件用于生成代码

    我们将使用jaxb2-maven-plugin来高效的生成domain代码,首先需要在pom.xml文件添加以下插件配置代码:

    <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>
            <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
            <clearOutputDir>false</clearOutputDir>
        </configuration>
    </plugin>
    

    该插件将使用 XJC工具作为代码生成引擎,XJC能将XML schema 文件转成带注解的代码;
    现在,我们就可以执行以上插件生成代码了;

    创建SOAP Webservice Endpoint

    StudentEndpoint类会处理所有访问该服务的请求,并委派给StudentRepository去处理,具体代码如下:

    package com.example.howtodoinjava.springbootsoapservice;
     
    import org.springframework.beans.factory.annotation.Autowired;
    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;
    import com.howtodoinjava.xml.school.StudentDetailsRequest;
    import com.howtodoinjava.xml.school.StudentDetailsResponse;
     
    @Endpoint
    public class StudentEndpoint
    {
        private static final String NAMESPACE_URI = "http://www.howtodoinjava.com/xml/school";
     
        private StudentRepository StudentRepository;
     
        @Autowired
        public StudentEndpoint(StudentRepository StudentRepository) {
            this.StudentRepository = StudentRepository;
        }
     
        @PayloadRoot(namespace = NAMESPACE_URI, localPart = "StudentDetailsRequest")
        @ResponsePayload
        public StudentDetailsResponse getStudent(@RequestPayload StudentDetailsRequest request) {
            StudentDetailsResponse response = new StudentDetailsResponse();
            response.setStudent(StudentRepository.findStudent(request.getName()));
     
            return response;
        }
    }
    

    对上面的几个注解做个简单说明(可以和Spring MVC的Controller做个类比,有点相似):

    1. @Endpoint 声明用于处理SOAP消息
    2. @PayloadRoot 根据namespace和localPart映射对应的处理方法
    3. @RequestPayload 声明进来的消息将会与该方法的参数映射
    4. @ResponsePayload 方法返回值的映射

    创建Data Repository

    出于简便考虑,我们将直接在代码里初始化相关数据,代码如下:
    创建StudentRepository.java,加上@Repository注解,添加findStudent()方法:

    package com.example.howtodoinjava.springbootsoapservice;
     
    import java.util.HashMap;
    import java.util.Map;
    import javax.annotation.PostConstruct;
    import org.springframework.stereotype.Component;
    import org.springframework.util.Assert;
    import com.howtodoinjava.xml.school.Student;
     
    @Component
    public class StudentRepository {
        private static final Map<String, Student> students = new HashMap<>();
     
        @PostConstruct
        public void initData() {
             
            Student student = new Student();
            student.setName("Sajal");
            student.setStandard(5);
            student.setAddress("Pune");
            students.put(student.getName(), student);
             
            student = new Student();
            student.setName("Kajal");
            student.setStandard(5);
            student.setAddress("Chicago");
            students.put(student.getName(), student);
             
            student = new Student();
            student.setName("Lokesh");
            student.setStandard(6);
            student.setAddress("Delhi");
            students.put(student.getName(), student);
             
            student = new Student();
            student.setName("Sukesh");
            student.setStandard(7);
            student.setAddress("Noida");
            students.put(student.getName(), student);
        }
     
        public Student findStudent(String name) {
            Assert.notNull(name, "The Student's name must not be null");
            return students.get(name);
        }
    }
    

    添加SOAP Webservice 配置

    添加一个带 @Configuration注解的配置类:

    package com.example.howtodoinjava.springbootsoapservice;
     
    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.wsdl11.DefaultWsdl11Definition;
    import org.springframework.xml.xsd.SimpleXsdSchema;
    import org.springframework.xml.xsd.XsdSchema;
     
    @EnableWs
    @Configuration
    public class Config extends WsConfigurerAdapter
    {
        @Bean
        public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext)
        {
            MessageDispatcherServlet servlet = new MessageDispatcherServlet();
            servlet.setApplicationContext(applicationContext);
            servlet.setTransformWsdlLocations(true);
            return new ServletRegistrationBean(servlet, "/service/*");
        }
     
        @Bean(name = "studentDetailsWsdl")
        public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema)
        {
            DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
            wsdl11Definition.setPortTypeName("StudentDetailsPort");
            wsdl11Definition.setLocationUri("/service/student-details");
            wsdl11Definition.setTargetNamespace("http://www.howtodoinjava.com/xml/school");
            wsdl11Definition.setSchema(countriesSchema);
            return wsdl11Definition;
        }
     
        @Bean
        public XsdSchema countriesSchema()
        {
            return new SimpleXsdSchema(new ClassPathResource("school.xsd"));
        }
    }
    
    • 该类继承了WsConfigurerAdapter类配置了注解驱动的 Spring-WS编程模式;
    • MessageDispatcherServlet - Spring-WS使用该类处理SOAP 请求,我们需要把该Servlet注入ApplicationContext ,以便Spring-WS能找到其它Bean;
    • DefaultWsdl11Definition 使用XsdSchema暴露了一个标准的的WSDL 1.1,bean的名字studentDetailsWsdl 将会作为wsdl 暴露出去的名称,我们可以通过http://localhost:8080/service/studentDetailsWsdl.wsdl路径访问;

    Spring boot SOAP webservice例子演示

    使用mvn clean install maven命名构建工程,并使用java -jar targetspring-boot-soap-service-0.0.1-SNAPSHOT.jar命令启动应用;

    执行完以上操作后,将会以默认的8080端口启动一个tomcat服务,本应用将部署在该服务里;

    现在我们可以访问http://localhost:8080/service/studentDetailsWsdl.wsdl路径,确认wsdl是否是正确的:
    file

    如果我们的wsdl没问题的话,我们可以使用该WSDL 在SOAP ui 里创建一个工程,并测试该应用,请求和响应示例如下:
    请求:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://www.howtodoinjava.com/xml/school">
       <soapenv:Header/>
       <soapenv:Body>
          <sch:StudentDetailsRequest>
             <sch:name>Sajal</sch:name>
          </sch:StudentDetailsRequest>
       </soapenv:Body>
    </soapenv:Envelope>
    

    响应

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Header/>
       <SOAP-ENV:Body>
          <ns2:StudentDetailsResponse xmlns:ns2="http://www.howtodoinjava.com/xml/school">
             <ns2:Student>
                <ns2:name>Sajal</ns2:name>
                <ns2:standard>5</ns2:standard>
                <ns2:address>Pune</ns2:address>
             </ns2:Student>
          </ns2:StudentDetailsResponse>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    

    file

    总结

    本文学习了如何使用Spring Boot创建SOAP webservice,同时也学习了如何利用wsdl生成代码,以及Spring-WS如何处理SOAP 请求

  • 相关阅读:
    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
    便携版WinSCP在命令行下同步文件夹
    ffmpeg (ffprobe)分析文件关键帧时间点
    sqlite删除数据或者表后,回收数据库文件大小
    ubuntu 20.04下 freeswitch 配合 fail2ban 防恶意访问
    ffmpeg使用nvenc编码的结论记录
    PC版跑跑卡丁车 故事模式 亚瑟传说章节 卡美洛庆典 2阶段 心灵之眼 攻略
    There was an error loading or playing the video
    Nvidia RTX Voice 启动报错修复方法
    火狐浏览器 关闭跨域限制
  • 原文地址:https://www.cnblogs.com/chenpi/p/9785958.html
Copyright © 2011-2022 走看看