最近要把一个很老的系统的接口对接到新的平台里,他原来接口使用的是webservice, 我问了我同事,这个接口支持rfc直连和po调用,(是啥我也不知道,估计这玩意比我年龄都大了吧)
先说一下代码生成
准备
sap连接:
http://xxx.com.cn:xxx/dir/wsdl?p=ic/c2cc333eab52e471f07eea50
注意:这个地址只是用来代码生成的,调用不能写这个地址,写这个xml中最下面有两个地址中的一个作为调用地址
<wsdl:service name="SI_ACDOCA_ZYD_OUTService">
<wsdl:port name="HTTP_Port" binding="p1:SI_ACDOCA_ZYD_OUTBinding">
<soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" location="http://xxx.xxxx.com.cn:xxx/XISOAPAdapter/MessageServlet?senderParty=&senderService=BC_COMMON&receiverParty=&receiverService=&interface=SI_ACDOCA_ZYD_OUT&interfaceNamespace=http%3A%2F%xxxx.com%2Fxi%2Fcom"/>
</wsdl:port>
<wsdl:port name="HTTPS_Port" binding="p1:SI_ACDOCA_ZYD_OUTBinding">
<soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" location="https://xxx.xxxx.com.cn:xxxx/XISOAPAdapter/MessageServlet?senderParty=&senderService=BC_COMMON&receiverParty=&receiverService=&interface=SI_ACDOCA_ZYD_OUT&interfaceNamespace=http%3A%2F%xxxx.com%xx%2Fcom"/>
</wsdl:port>
</wsdl:service>
环境变量配置
- 下载二进制文件
进入连接下载3.4.10的文件 -
将解压后的二进制文件配置到环境变量
代码生成
方式一
-
本地新建文件auth.txt
-
写入内容
http://用户名:密码@xxxx.xxx.com.cn:xxx/dir/wsdl?p=ic/xxxxxxxxxxxxxxxxxxx
- 在本地执行命令
wsimport -d E:\zlb\test -Xauthfile E:\zlb\test\auth.txt -p com.xx.dms.xxxx.xx -encoding utf-8 -keep http://xxxx.xxxx.com.cn:xxx/dir/wsdl?p=ic/xxxxxxxxxxxxxxxxxxxxxxxx
方式二
- 访问sap地址,将xml保存到本地
-
在本地执行命令
wsimport -s . wsdl.xml -p 包名 -encoding utf-8
注意: 一定不要使用代理,会报错
代码调用
引入jar包
<webservice-cxf.version>3.4.10</webservice-cxf.version>
<!-- webservice-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<version>{webservice-cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>{webservice-cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${webservice-cxf.version}</version>
</dependency>
<!-- webservice-->
封装抽象类
/**
* @author: lpy
* @Date: 2023/11/24
* @desc: P: execute方法的执行参数 R:execute方法的返回值
*/
public abstract class WebServiceExecute<P,R> {
/**
* 抽象执行方法,子类需要重写,然后设置
* @param parameters 请求体(代码自动生成的,例如coszyd01就是包含了items和header的类ZFIACDOCAZYD01)
* @return
*/
public abstract R execute(P parameters);
/**
* 设置用户名密码,获取到auth后的bean,用来调用接口,并且设置连接信息
* @param address 调用地址
* @param username
* @param password
* @param serviceClass 生成的代码中的接口名
* @param <T>
* @return
*/
protected <T> T createInstanceAndSetConnectionInf(String address, String username, String password, Class<T> serviceClass){
JaxWsProxyFactoryBean clientFactory = new JaxWsProxyFactoryBean();
clientFactory.setAddress(address);
clientFactory.setServiceClass(SIACDOCAZYDOUT.class);
clientFactory.setUsername(username);
clientFactory.setPassword(password);
T cast = serviceClass.cast(clientFactory.create());
// 设置连接信息
setConnectInformation(cast);
return cast;
}
/**
* 设置连接信息
* @param service
* @param <T>
*/
protected <T> void setConnectInformation(T service) {
ClientImpl client = (ClientImpl) ClientProxy.getClient(service);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(30 * 60 * 1000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setReceiveTimeout(30 * 60 * 1000);
http.setClient(httpClientPolicy);
}
/**
* 是否执行成功
* @param resp
* @return
*/
public abstract boolean isExecutedSuccess(R resp);
}
execute方法
/**
* @author: lpy
* @Date: 2023/11/23
*/
@Component
@Slf4j
public class CosZYD01Execute extends WebServiceExecute<ZFIACDOCAZYD01, ZFIACDOCAZYD01Response> {
@Value("${ws.coszyd01.address}")
private String address;
@Value("${ws.coszyd01.username}")
private String username;
@Value("${ws.coszyd01.password}")
private String password;
@Override
public ZFIACDOCAZYD01Response execute(ZFIACDOCAZYD01 parameters) {
// 设置访问地址 用户名 密码
SIACDOCAZYDOUT getConfirmationDeduction = super.createInstanceAndSetConnectionInf(address, username, password, SIACDOCAZYDOUT.class);
/**执行方法*/
log.info("coszyd01-execute-paramters:{}", JSON.toJSONString(parameters));
ZFIACDOCAZYD01Response returnInfo = getConfirmationDeduction.siACDOCAZYDOUT(parameters);
log.info("coszyd01-execute-return:{}", JSON.toJSONString(returnInfo));
return returnInfo;
}
/**
* 消息类型: S 成功,E 错误,W 警告,I 信息,A 中断
*
* @param resp
* @return
*/
@Override
public boolean isExecutedSuccess(ZFIACDOCAZYD01Response resp) {
String EV_STATUS = resp.getEVSTATUS();
return "S".equals(EV_STATUS);
}
}
调用
@GetMapping("/cos01Test")
public String tem() {
CosZYD01ObjectFactory objectFactory = new CosZYD01ObjectFactory();
// 组装请求体
// 请求体
ZFIACDOCAZYD01 parameters= objectFactory.createZFIACDOCAZYD01();
// header
ZSFIACDOCZYD01HEADER parameterslist = objectFactory.createZSFIACDOCZYD01HEADER();
parameterslist.setBUSINESSTYPE("xx");
parameterslist.setCOMPCODE("xx");
ZFIACDOCAZYD01.ITITEMS ititems = new ZFIACDOCAZYD01.ITITEMS();
ZSFIACDOCZYD01ITEM item = objectFactory.createZSFIACDOCZYD01ITEM();
item.setAMOUNT1(new BigDecimal("114"));
ititems.getItem().add(item);
// header赋值
parameters.setISHEADER(parameterslist);
// items赋值
parameters.setITITEMS(ititems);
// 调用
ZFIACDOCAZYD01Response resp = cosZYD01Execute.execute(parameters);
boolean executedSuccess = cosZYD01Execute.isExecutedSuccess(resp);
return executedSuccess+"";
}
}
记录
中间花费了很长时间,不是因为代码问题,调试了两天,一直出现405,method is not allowed, 我万万没想到是调用地址的问题,也就是文章一开头那里写的,我万万没想到这个xml竟然不是调用的地址,巨恶心,我讨厌webservice,那里有json这么轻巧啊