WebService工具类

以下工具集成了多种方式调用webservice,如http方式,axis方式,动态生成客户端方式等 ,是为笔者实际工作中提炼的,方便大家直接套用,常用方法都有调用示列。

一、整个工具类代码

package com.gykjit.spd.edi.util;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.types.Schema;
import org.apache.commons.collections.MapUtils;
import com.google.common.collect.Lists;
import org.springframework.util.StringUtils;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;


/**
 * @author hulei
 * @Date 2022/9/8 18:31
 */
public class WebServiceUtil {

    private final static Logger log = LoggerFactory.getLogger(WebServiceUtil.class);


    /**
     *
     * @param url
     * @param soapActionURI
     * @param nameSpace
     * @param operationName
     * @param params
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T call(String url,String soapActionURI, String nameSpace,String operationName, Map<String, String> params, Class<T> clazz) {
         soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
        try {
            Service service = new Service();

            SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
            header.setNamespaceURI(nameSpace);

            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);

            call.setOperationName(new QName(nameSpace, operationName));

            // 添加参数
            List<String> parameterList = Lists.newArrayList();
            if (params != null) {
                Set<String> paramsKey = params.keySet();
                for (String key : paramsKey) {
                    call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING, ParameterMode.IN);
                    String pValue = MapUtils.getString(params, key);
                    header.addChildElement(key).setValue(pValue);
                    parameterList.add(pValue);
                }
            }
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapActionURI);
            call.addHeader(header);

            //进行序列化  实体类也要序列化 implements Serializable
            call.registerTypeMapping(clazz, new QName(nameSpace, soapActionURI),
                      new BeanSerializerFactory(clazz, new QName(nameSpace, soapActionURI)),
                      new BeanDeserializerFactory(clazz, new QName(nameSpace, soapActionURI)));
            //设置输出的类
            call.setReturnClass(clazz);
            // 接口返回结果
            T result = (T) call.invoke(parameterList.toArray());
            log.info("调用 WebService 接口返回===>" + result);
            return result;
        } catch (Exception e) {
            log.error("调用 WebService 接口错误信息==>" + e.getMessage());
        }
        return null;
    }

    /**
     *
     * @param url
     * @param soapActionURI
     * @param nameSpace
     * @param operationName
     * @param params
     * @return
     */
    public static String call(String url,String soapActionURI,String nameSpace,String operationName, Map<String, String> params) {
        soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
        try {
            Service service = new Service();

            SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
            header.setNamespaceURI(nameSpace);

            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);

            call.setOperationName(new QName(nameSpace, operationName));

            // 添加参数
            List<String> parameterList = Lists.newArrayList();
            if (params != null) {
                Set<String> paramsKey = params.keySet();
                for (String key : paramsKey) {
                    call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING, ParameterMode.IN);
                    String pValue = MapUtils.getString(params, key);
                    header.addChildElement(key).setValue(pValue);
                    parameterList.add(pValue);
                }
            }
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapActionURI);
            call.addHeader(header);
            // 设置返回类型
            call.setReturnType(new QName(nameSpace, operationName), String.class);
            // 接口返回结果
            String result = (String) call.invoke(parameterList.toArray());
            log.info("调用 WebService 接口返回===>" + result);
            return result;
        } catch (Exception e) {
            log.error("调用 WebService 接口错误信息==>" + e.getMessage());
        }
        return null;
    }

    /**
     * 设置参数模式(IN,OUT)
     * @param url
     * @param soapActionURI
     * @param nameSpace
     * @param operationName
     * @param params
     * @param ParameterModeType 参数模式(IN,OUT)
     * @return
     */
    public static String callAndSetParameterModeType(String url,String soapActionURI,String nameSpace,String operationName, Map<String, String> params,
                                                       Map<String,String> ParameterModeType) {
        soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
        try {
            Service service = new Service();

            SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
            header.setNamespaceURI(nameSpace);

            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);

            call.setOperationName(new QName(nameSpace, operationName));

            // 添加参数
            List<String> parameterList = Lists.newArrayList();
            //设置参数模式处理函数
            Function<String,ParameterMode> function = (key)->{
                if("OUT".equals(key)){
                    return ParameterMode.OUT;
                }
                return ParameterMode.IN;
            };
            if (params != null) {
                Set<String> paramsKey = params.keySet();
                for (String key : paramsKey) {
                    call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING,function.apply(MapUtils.getString(ParameterModeType, key)));
                    String pValue = MapUtils.getString(params, key);
                    header.addChildElement(key).setValue(pValue);
                    parameterList.add(pValue);
                }
            }
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapActionURI);
            call.addHeader(header);
            // 设置返回类型
            call.setReturnType(new QName(nameSpace, operationName), String.class);
            // 接口返回结果
            String result = (String) call.invoke(parameterList.toArray());
            log.info("调用 WebService 接口返回===>" + result);
            return result;
        } catch (Exception e) {
            log.error("调用 WebService 接口错误信息==>" + e.getMessage());
        }
        return null;
    }

    /**
     * WebService - 调用接口
     *
     * @param operationName 函数名
     * @param params     参数
     * @return 返回结果(String)
     */
    public static String callReturnSchema(String url,String soapActionURI,String nameSpace,String operationName, Map<String, String> params) {
        soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
        try {
            Service service = new Service();

            SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
            header.setNamespaceURI(nameSpace);

            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);

            call.setOperationName(new QName(nameSpace, operationName));

            // 添加参数
            List<String> parameterList = Lists.newArrayList();
            if (params != null) {
                Set<String> paramsKey = params.keySet();
                for (String key : paramsKey) {
                    call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING, ParameterMode.IN);
                    String pValue = MapUtils.getString(params, key);
                    header.addChildElement(key).setValue(pValue);
                    parameterList.add(pValue);
                }
            }
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapActionURI);
            call.addHeader(header);
            // 设置返回类型
            call.setReturnType(XMLType.XSD_SCHEMA);
            // 接口返回结果
            Schema schemaResult = (Schema)call.invoke(parameterList.toArray());
            StringBuilder result = new StringBuilder();
            for(int i = 0; i<schemaResult.get_any().length; i++){
                result.append(schemaResult.get_any()[i]);
            }
            log.error("调用 WebService 接口返回===>" + result);
            return result.toString();
        } catch (Exception e) {
            log.error("调用 WebService 接口错误信息==>" + e.getMessage());
        }
        return null;
    }

    /**
     * 动态调用webService
     * @param url
     * @param operationName
     * @param params
     * @return
     * @throws Exception
     */
    public static Object dcfSoap(String url, String operationName, String... params) throws Exception {
        /// 创建动态客户端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient(url);
        //超时等待设置,防止处理时间过长断开连接
        HTTPConduit conduit = (HTTPConduit) client.getConduit();
        HTTPClientPolicy policy = new HTTPClientPolicy();
        long timeout = 10 * 60 * 1000;
        policy.setConnectionTimeout(timeout);//连接时间
        policy.setReceiveTimeout(timeout);//接受时间
        conduit.setClient(policy);
        // 需要密码的情况需要加上用户名和密码
        // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
        Object[] objects;
        try {
            // invoke("方法名",参数1,参数2,参数3....);
            //这里注意如果是复杂参数的话,要保证复杂参数可以序列化
            objects = client.invoke(operationName, (Object) params);
            System.out.println("返回数据:" + objects[0]);
        } catch (java.lang.Exception e) {
            log.info("返回数据异常:"+e.getMessage());
            return e.getMessage();
        }
        return objects[0];
    }


    /**
     * http方式调用webService
     * @param wsdlUrl 远程地址
     * @param SOAPAction 标识http请求目的地
     * @param soapXml 请求参数
     * @return 返回的是soap报文(可用dom4j解析)
     */
    public static String HttpSendSoapPost(String wsdlUrl,String SOAPAction,String soapXml){
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        String result = null;// 返回结果字符串
        OutputStream out;
        try {
            // 创建远程url连接对象
            URL url = new URL(wsdlUrl);
            // 通过远程url连接对象打开一个连接,强转成httpURLConnection类

            connection = (HttpURLConnection) url.openConnection();
            // 设置连接方式:GET,POST
            connection.setRequestMethod("POST");

            connection.setDoInput(true);
            connection.setDoOutput(true);

            connection.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
            //这里必须要写,否则出错,根据自己的要求写,默认为空
            connection.setRequestProperty("SOAPAction", SOAPAction != null ? SOAPAction : "");
            // 设置连接主机服务器的超时时间:15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间:200000毫秒
            connection.setReadTimeout(200000);

            // 发送请求
            connection.connect();
            out = connection.getOutputStream(); // 获取输出流对象
            connection.getOutputStream().write(soapXml.getBytes(StandardCharsets.UTF_8)); // 将要提交服务器的SOAP请求字符流写入输出流
            out.flush();
            out.close();
            // 通过connection连接,获取输入流
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // 封装输入流is,并指定字符集
                br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
                // 存放数据
                StringBuilder sbf = new StringBuilder();
                String temp;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 关闭远程连接
            if(connection != null){
                connection.disconnect();
            }
        }
        return result;
    }

    public static String sendWebService(String url, String xml) {
        try {
            URL soapUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) soapUrl.openConnection();

            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            //设置输入输出,新创建的connection默认是没有读写权限的
            connection.setDoInput(true);
            connection.setDoOutput(true);
            //这里设置请求头类型为xml,传统http请求的是超文本传输格式text/html
            connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
            connection.getOutputStream().write(xml.getBytes(StandardCharsets.UTF_8)); // 将要提交服务器的SOAP请求字符流写入输出流

            log.info("写入xml入参:{}", xml);
            InputStream inputStream = connection.getInputStream();
            if (inputStream != null) {
                byte[] bytes;
                bytes = new byte[inputStream.available()];
                int result = inputStream.read(bytes);
                if(result == -1){
                    log.info("流读取完毕!");
                }
                //将字节数组转换为字符串输出
                return new String(bytes, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            log.info("sendWebService方法报错:{}", e.getMessage());
            return null;
        }
        return null;
    }
}

二、pom依赖引入

可能有复制多了的依赖,可自己尝试去除,工具类不飘红报错就行

        <dependency>
            <groupId>javax.jws</groupId>
            <artifactId>javax.jws-api</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.1.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.1.11</version>
        </dependency>
        <!--axis-->
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis-jaxrpc</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
        </dependency>

三、方法调用示列详解

 3.1 以下调用的是工具类第二个方法,返回的是string字符串,具体是json还是xml,按照实际情况解析就行

具体参数解释

* @param url 第三方服务地址
* @param soapActionURI  自行百度soapAction
* @param nameSpace 命名空间,自行百度soap
* @param operationName 调用方法名
* @param params 调用参数,示例的参数名是xml

3.2 接着是 dcfSoap()方法

* 动态调用webService
* @param url 第三方服务地址
* @param operationName 方法名
* @param params 动态参数,可以写多个

3.3 HttpSendSoapPost(此方法最常用,但是报文头需要自己拼,我一般用soapUI工具连好对方服务,会自动生成,参数自己拼接上,这个调用不太会出现一些乱七八糟的问题)

 1是构建xml,2是把xml放在soapui生成的报文头的参数里,3直接调用工具类发送

实在不会调用的,评论区找我吧

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
### 回答1: Spring Boot集成CXF框架可以方便地调用Web服务。以下是使用Spring Boot和CXF调用Web服务的步骤: 1. 在pom.xml文件中添加CXF依赖: ``` <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.3.6</version> </dependency> ``` 2. 创建一个接口来定义Web服务的操作: ``` @WebService public interface MyWebService { @WebMethod String sayHello(String name); } ``` 3. 创建一个实现类来实现接口中定义的操作: ``` @Service @WebService(endpointInterface = "com.example.MyWebService") public class MyWebServiceImpl implements MyWebService { @Override public String sayHello(String name) { return "Hello " + name + "!"; } } ``` 4. 在应用程序的配置文件中添加CXF配置: ``` cxf: servlet: path: /services/* jaxws: properties: javax.xml.ws.soap.http.soapaction.use: "false" ``` 5. 在控制器中注入Web服务并调用它: ``` @RestController public class MyController { @Autowired private MyWebService myWebService; @GetMapping("/hello/{name}") public String sayHello(@PathVariable String name) { return myWebService.sayHello(name); } } ``` 6. 启动应用程序并访问Web服务: ``` http://localhost:8080/services/MyWebServiceImpl?wsdl ``` 以上就是使用Spring Boot和CXF调用Web服务的步骤。 ### 回答2: Spring Boot是一个使用习惯优秀的Web应用开发框架,它可以帮助我们快速构建应用,提高开发效率。而CXF是一个开源的WebService框架,它提供了一系列的API和工具来帮助开发人员可以很轻易地实现一个基于SOAP的Web服务。 在Spring Boot调用CXF框架中的WebService,需要进行以下步骤: 1. 添加依赖 在pom.xml中添加CXF和Spring Boot Web依赖: ``` <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.3.1</version> </dependency> </dependencies> ``` 2. 编写WebService客户端类 编写一个类来调用CXF产生的webservice服务,其中包括Endpoint指向和需要调用的方法等信息。 ``` @Service public class WebServiceClient { @Autowired private JaxWsProxyFactoryBean jaxWsProxyFactoryBean; private HelloPortType helloPortType; public String sayHello(final String name) { initPortType(); return helloPortType.sayHello(name); } private void initPortType() { if (helloPortType == null) { jaxWsProxyFactoryBean.setServiceClass(HelloPortType.class); jaxWsProxyFactoryBean.setAddress("http://localhost:8080/hello"); helloPortType = (HelloPortType) jaxWsProxyFactoryBean.create(); } } } ``` 3. 编写WebService 通过CXF创建web服务,并实现接口提供服务,返回接口需要的数据。 ``` @javax.jws.WebService(serviceName = "HelloService", portName = "HelloPort", targetNamespace = "http://www.example.org/HelloService/", endpointInterface = "org.example.service.HelloPortType") public class HelloPortTypeImpl implements HelloPortType { private final static Logger LOGGER = LoggerFactory.getLogger(HelloPortTypeImpl.class); @Resource private WebServiceContext webServiceContext; @Override public String sayHello(final String name) { final MessageContext mc = webServiceContext.getMessageContext(); final HttpServletRequest req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST); LOGGER.info("服务SayHello calling, name: {}, IP addr:{}, sessionId: {}", name, req.getRemoteAddr(), req.getSession().getId()); return String.format("Hello, %s!", name); } } ``` 4. 进行测试 在控制器中注入WebService客户端类,并进行测试。 ``` @RestController @RequestMapping("/test") public class TestController { @Autowired private WebServiceClient webServiceClient; @GetMapping("/sayHello") public String sayHello(@RequestParam(value = "name") final String name) { return webServiceClient.sayHello(name); } } ``` 总的来说,Spring Boot和CXF框架结合起来使用,可以很方便地调用WebService,提供服务的代码也可以很容易地进行编写。 ### 回答3: SpringBoot是一个非常受欢迎的Java框架,其有很多优秀的特性让使用者更方便地进行应用的开发。其中,SpringBoot与CXF框架结合使用来调用Webservice可以非常简单地完成。本文将介绍SpringBoot与CXF框架结合使用来调用Webservice。 首先,我们需要在pom.xml文件中加入CXF及相关依赖。 ```xml <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.2.14</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transport-http</artifactId> <version>3.2.14</version> </dependency> ``` 然后,我们需要在配置文件中设置一些参数,具体如下: ```yaml cxf: client: simple.frontend: true logging.enabled: true timeout: connect: 2000 receive: 5000 path: /ws servlet: url-pattern: /soap/* ``` 在上述配置中,我们开启了日志记录,设置了连接超时和读取超时时间,以及指明了Webservice的路径。 接下来就可以创建一个接口来调用我们的Webservice。例如,我们想要调用一个返回学生列表的Webservice: ```java @WebService public interface StudentWebService { @WebMethod List<Student> getStudents(); } ``` 我们使用CXF的JAX-WS Frontend创建了一个接口,同时使用@WebService注解来标记该接口。然后我们就可以创建一个实现类来实现该接口: ```java @Service public class StudentWebServiceImpl implements StudentWebService { @Override public List<Student> getStudents() { // 调用Webservice,返回学生列表 return new ArrayList<>(); } } ``` 在上述实现类中,我们使用@Service注解来标记该类为SpringBoot的一个服务,同时实现了我们在接口中声明的getStudents()方法,去调用Webservice并返回学生列表。在该方法中,我们可以使用Spring提供的RestTemplate或者使用CXF的Client接口来进行调用。 然后我们同样使用CXF开放一个服务端口,供客户端调用: ```java @Configuration public class CxfConfig { @Bean(name = Bus.DEFAULT_BUS_ID) public SpringBus springBus() { return new SpringBus(); } @Bean public ServletRegistrationBean<CXFServlet> cxfServlet() { return new ServletRegistrationBean<CXFServlet>(new CXFServlet(), "/soap/*"); } @Bean public StudentWebService studentWebService() { return new StudentWebServiceImpl(); } @Bean public Endpoint endpoint() { EndpointImpl endpoint = new EndpointImpl(springBus(), studentWebService()); endpoint.publish("/StudentWebService"); return endpoint; } } ``` 在上述代码中,我们创建了一个CXFServlet,并将其映射到/soap/*路径下,同时创建了一个WebService的实现类,在SpringBoot启动时通过Endpoint暴露出来。这样我们就可以在客户端中通过CXF框架来访问Webservice了。 总结一下,SpringBoot与CXF框架结合使用调用Webservice可以非常方便地完成。我们只需要提供一个接口,实现其方法并使用CXF暴露出去,就可以在客户端通过CXF框架来访问了。同时,我们还可以使用CXF的一些特性来定制化我们的调用过程,包括定制连接超时、读取超时、日志记录等。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值