行业知识
SpringBoot集成WebService
前言
首先,WebService是一个面向服务的历史技术产品,现在基本都使用restful的http接口;会使用到WebService的一般都是国企产品(这意味着没得选,并且很难找到开发人员对接,出入参只能自己摸索),例如中国移动的内网隔离的短信平台。
对接WebService之前,有一些基础建议先放在前面:
1.对XML语言有一定的基础,在获取一个wsdl服务端地址时,先用浏览器访问地址,阅读对应的xml内容,对自己关心的operation(解析到java中就是对应的函数方法)进行仔细地阅读,观察这个operation的入参情况(着重确定参数type类型)
2.下载soapui工具,进行wsdl服务端的在线调试(类似postman),很方便,先确定链路是通的,再进行代码的编写。
实战遇到的问题
1.此处不应有9
为了快速出活,我这边的实践是使用apache-cxf生成webservice的java代理代码。出现这个错误是因为JAVA_HOME环境变量的配置问题,我这边的实际情况是电脑安装了JDK17,先卸载这个JDK17之后,电脑只保留JDK8之后问题得到解决。
2.No scheme found in URI
在网络协议中,出现这个问题就是没指定http或者https,但是本次实战指定的uri是固定的,所以不会有问题,在soapui中也出现这个问题,所以确定是入参问题。观察对应的xml解析发现某个参数是anyUri类型,这个类型生成的代理代码是List ,也就是说这个String必须是uri格式的,实际存储的是手机号码,在xml协议中的手机号码uri格式是需要携带 【tel:】标识的,所以完整参数是: tel:135****6666 这样。
实战
生成客户端代码
生成Java客户端代理代码,自己百度apache-cxf官网,我下载的是apache-cxf 3.5.8版本的Windows包,配置好环境变量之后,使用下面的命令在cmd中生成客户端代码
wsdl2java -encoding utf-8 -d E:\ws http://xxxx?wsdl
依赖
外面的教程一般是引入apache-cxf依赖或者spring自己的ws依赖,我只需要使用到WebServiceTemplate,所以只引入核心包,依赖是
org.springframework.ws spring-ws-core 3.0.7.RELEASE
Config配置信息
将客户端代码复制到自己的工程中,一般这个代码有自己的包路径,所以放在main下面,跟自己的工程目录平级;生成的代码会很多,其中跟自己需求关系很少,有时间的可以自己将不相关的JavaBean等文件删掉。下面是基本的配置代码
@Configurationpublic class WebServiceConfig { @Bean public Jaxb2Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); // 设置需要转换的 Java 类所在的包,避免程序启动报错 marshaller.setPackagesToScan("org.csapi"); return marshaller; } @Bean public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller) { WebServiceTemplate template = new WebServiceTemplate(); template.setMarshaller(marshaller); template.setUnmarshaller(marshaller); //设置默认的请求url template.setDefaultUri("http://***/**"); return template; }} 客户端调用伪代码
import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import org.springframework.ws.client.core.WebServiceTemplate;import javax.annotation.Resource;import java.util.Collections;import java.util.List;@Componentpublic class WebServiceClient { @Resource private WebServiceTemplate webServiceTemplate; public void sendSms(String content, List phones) { phones.forEach(phoneNo -> { SendRequest request = new SendRequest(); request.setMessage(content); request.setDestinationAddresses(Collections.singletonList(String.format("tel:%s", phoneNo))); ThreadPool.execute(() -> { try { //WebServiceTemplate内部封装了对operation的自动判定,根据入参请求中的注解,自己判定需要用哪个operation并转换response, 所以尽量将生成的所有代理类代码复制出来 Object object = webServiceTemplate.marshalSendAndReceive(request); } catch (Exception exception) { } }); }); }} 总结
没有什么特别的总结,over