openFein 调用webservice,soap+xml

一、服务端:

1.1目录结构:

1.2maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>soapdemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-features-logging</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.4.Final</version>
        </dependency>

    </dependencies>

</project>

1.3WebServiceConfig配置类

package com.soap.config;


import com.soap.service.StudentService;
import org.apache.cxf.Bus;
import org.apache.cxf.ext.logging.LoggingInInterceptor;
import org.apache.cxf.ext.logging.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.xml.ws.Endpoint;

/**
 * @author Administrator
 * @date 2019/01/30
 */
@Configuration
public class WebServiceConfig {

    @Resource
    private Bus bus;

    @Resource
    private StudentService studentService;

    @Bean
    public Endpoint endpointStudentService() {
        EndpointImpl endpoint=new EndpointImpl(bus,studentService);
        endpoint.getInInterceptors()
                .add(loggingInInterceptor());
        endpoint.getOutInterceptors()
                .add(loggingOutInterceptor());
        endpoint.publish("/studentService");
        return endpoint;

    }

    @Bean
    public LoggingInInterceptor loggingInInterceptor() {
        return new LoggingInInterceptor();
    }

    @Bean
    public LoggingOutInterceptor loggingOutInterceptor() {
        return new LoggingOutInterceptor();
    }
}

1.3Student实体类

package com.soap.entity;

public class Student {
    private String stuName;
    private Integer stuAge;

    public Student() {}

    public Student(String stuName, Integer stuAge) {
        this.stuName = stuName;
        this.stuAge = stuAge;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Integer getStuAge() {
        return stuAge;
    }

    public void setStuAge(Integer stuAge) {
        this.stuAge = stuAge;
    }
}

1.4提供服务类

package com.soap.service;

import com.soap.entity.Student;

import javax.jws.WebMethod;
import javax.jws.WebService;
import java.util.List;

@WebService(targetNamespace = "http://service.soap.com")//  命名空间,建议包名倒写
public interface StudentService {

    @WebMethod
    List<Student> getStudentList();
}

1.5服务实现类

package com.soap.service.impl;

import com.soap.entity.Student;
import com.soap.service.StudentService;
import org.springframework.stereotype.Component;
import javax.jws.WebService;
import java.util.Arrays;
import java.util.List;

/**
 * @author Administrator
 * @date 2019/01/30
 */
@WebService(serviceName = "StudentService",
        targetNamespace = "http://service.soap.com",
        endpointInterface = "com.soap.service.StudentService")
@Component
public class StudentServiceImpl implements StudentService {
    @Override
    public List<Student> getStudentList() {
        Student stu1 = new Student("学生1",25);
        Student stu2 = new Student("学生2",30);
        return Arrays.asList(stu1,stu2);
    }
}

1.6启动类

package com.soap;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SoapBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SoapBootApplication.class,args);
    }
}

1.7 application.yml文件

server:
  port: 8081
  servlet:
    context-path: /

1.8启动后访问地址:http://localhost:8081/services/studentService?wsdl

1.9====================服务端配置完成================================

二、客户端

2.1目录结构

 2.1maven依赖,其他依赖自行添加

<dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-jaxb</artifactId>
        </dependency>

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-jaxrs</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-soap</artifactId>
            <version>10.2.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>10.10.1</version>
        </dependency>

<!--        openfeign远程调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2.2ConvertConfig配置类(解析xml)

package com.example.consumer.config;


import feign.Logger;
import feign.Util;
import feign.codec.Decoder;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.jaxb.JAXBContextFactory;
import org.springframework.context.annotation.Bean;
import org.w3c.dom.Document;

import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.*;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.ws.soap.SOAPFaultException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import static javax.xml.soap.SOAPConstants.DEFAULT_SOAP_PROTOCOL;

public class ConvertConfig {
    private Charset charsetEncoding = StandardCharsets.UTF_8;
    private String soapProtocol = DEFAULT_SOAP_PROTOCOL;

    private static final JAXBContextFactory jaxbContextFactory = new JAXBContextFactory.Builder()
            .withMarshallerJAXBEncoding("UTF-8")
            .build();

    @Bean
    public Encoder feignEncoder() {
        return (object, bodyType, template) -> {
            if (!(bodyType instanceof Class)) {
                throw new UnsupportedOperationException(
                        "SOAP only supports encoding raw types. Found " + bodyType);
            }
            try {
                Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
                Marshaller marshaller = jaxbContextFactory.createMarshaller((Class<?>) bodyType);
                marshaller.marshal(object, document);
                SOAPMessage soapMessage = MessageFactory.newInstance(soapProtocol).createMessage();
                SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
                soapEnvelope.addNamespaceDeclaration("ser", "http://service.soap.com");
                soapMessage.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charsetEncoding.displayName());
                soapMessage.getSOAPBody().addDocument(document);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                soapMessage.writeTo(bos);
                template.body(new String(bos.toByteArray()).replaceAll("getStudentList", "ser:getStudentList"));
            } catch (SOAPException | JAXBException | ParserConfigurationException|IOException| TransformerFactoryConfigurationError e) {
                throw new EncodeException(e.toString(), e);
            }
        };
    }

    @Bean
    public Decoder feignDecoder() {
        return (response, type) ->{
            try {
                if (response.status() != 404 && response.status() != 204) {
                    if (response.body() == null) {
                        return null;
                    } else {
                        SOAPMessage message = MessageFactory.newInstance(soapProtocol).createMessage(null,response.body().asInputStream());
                        SOAPBody soapBody = message.getSOAPBody();
                        if (soapBody != null) {
                            if (message.getSOAPBody().hasFault()) {
                                throw new SOAPFaultException(message.getSOAPBody().getFault());
                            }
                            //重要!!!!
                            Class<?> tt =(Class<?>)type;
                            Unmarshaller unmarshaller = jaxbContextFactory.createUnmarshaller(tt);

                            return unmarshaller.unmarshal(soapBody.extractContentAsDocument(),tt).getValue();
                        }
                    }
                } else {
                    return Util.emptyValueOf(type);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return Util.emptyValueOf(type);
        };
    }

    @Bean
    feign.Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

2.3GetStudentList实体类

package com.example.consumer.soap.entity;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class GetStudentList {
}

2.4GetStudentListResponse实体类

package com.example.consumer.soap.entity;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@XmlRootElement(name = "getStudentListResponse")
@XmlAccessorType(XmlAccessType.FIELD)
public class GetStudentListResponse {
    @XmlElement(name = "return")
    private List<Student> students;

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }
}

2.5 Student实体类

package com.example.consumer.soap.entity;

public class Student {
    private int stuAge;
    private String stuName;

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public int getStuAge() {
        return stuAge;
    }

    public void setStuAge(int stuAge) {
        this.stuAge = stuAge;
    }
}

2.6 feign远程调用类

package com.example.consumer.soap.feign;

import com.example.consumer.config.ConvertConfig;
import com.example.consumer.soap.entity.GetStudentList;
import com.example.consumer.soap.entity.GetStudentListResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;


@FeignClient(name = "SoapFeign",url = "http://localhost:8081",configuration = {ConvertConfig.class})
public interface SoapFeign {
    @PostMapping(value = "/services/studentService",consumes = {MediaType.TEXT_XML_VALUE})
    public GetStudentListResponse getStudentList(GetStudentList getStudentList);
}

2.7 启动类

package com.example.consumer;

import com.alibaba.fastjson.JSON;

import com.example.consumer.soap.entity.GetStudentListResponse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import java.io.ByteArrayInputStream;

@SpringBootApplication
@EnableFeignClients(basePackages = {"com.example.consumer.soap.feign"})
public class ConsumerApplication {
    public static void main(String[] args){
        ConsumerApplication consumerApplication=new ConsumerApplication();
//        try {
//            consumerApplication.method();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        SpringApplication.run(ConsumerApplication.class, args);
    }
    //可进行测试
    public void method() throws Exception {
        String example ="<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "   <soap:Body>\n" +
                "      <ns2:getStudentListResponse xmlns:ns2=\"http://service.soap.com\">\n" +
                "         <return>\n" +
                "            <stuAge>25</stuAge>\n" +
                "            <stuName>学生1</stuName>\n" +
                "         </return>\n" +
                "         <return>\n" +
                "            <stuAge>30</stuAge>\n" +
                "            <stuName>学生2</stuName>\n" +
                "         </return>\n" +
                "      </ns2:getStudentListResponse>\n" +
                "   </soap:Body>\n" +
                "</soap:Envelope>";
        SOAPMessage message = MessageFactory.newInstance().createMessage(null,
                new ByteArrayInputStream(example.getBytes()));
        Unmarshaller unmarshaller = JAXBContext.newInstance(GetStudentListResponse.class).createUnmarshaller();
        JAXBElement<GetStudentListResponse> unmarshal = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), GetStudentListResponse.class);
        GetStudentListResponse value = unmarshal.getValue();
        System.out.println(JSON.toJSONString(value));
    }

}

2.8 开启feign日志

logging:
  level:
    com.example.consumer.soap.feign.SoapFeign: debug

2.9 controller类

  @Resource
    private SoapFeign soapFeign;
    @GetMapping("/soap")
//R类,可以用Map代替
    public R testSoap() {
        GetStudentListResponse response= soapFeign.getStudentList(new GetStudentList());
        return R.success().put("students:",response);
    }

3.0 xml或wsdl文件

<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.soap.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="StudentService" targetNamespace="http://service.soap.com">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.soap.com" elementFormDefault="unqualified" targetNamespace="http://service.soap.com" version="1.0">
<xs:element name="getStudentList" type="tns:getStudentList"/>
<xs:element name="getStudentListResponse" type="tns:getStudentListResponse"/>
<xs:complexType name="getStudentList">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="getStudentListResponse">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:student"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="student">
<xs:sequence>
<xs:element minOccurs="0" name="stuAge" type="xs:int"/>
<xs:element minOccurs="0" name="stuName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="getStudentListResponse">
<wsdl:part element="tns:getStudentListResponse" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:message name="getStudentList">
<wsdl:part element="tns:getStudentList" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:portType name="StudentService">
<wsdl:operation name="getStudentList">
<wsdl:input message="tns:getStudentList" name="getStudentList"> </wsdl:input>
<wsdl:output message="tns:getStudentListResponse" name="getStudentListResponse"> </wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="StudentServiceSoapBinding" type="tns:StudentService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getStudentList">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getStudentList">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getStudentListResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="StudentService">
<wsdl:port binding="tns:StudentServiceSoapBinding" name="StudentServiceImplPort">
<soap:address location="http://localhost:8081/services/studentService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

3.1可用soapUI(soap请求,推荐)、postman(post请求)进行测试

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值