使用 Apache CXF 生成 Java 代码并调用 WebServic 接口
如果在工作中经常需要调用 WebService 接口,可以使用 Apache CXF 工具进行代码的生成,可以极大简化编码时间。这里将描述如何使用该工具,以及在调用 WebService 中遇到的一些问题和这些问题的解决方法。
基本操作
一、下载 Apache CXF :https://cxf.apache.org/download.html
二、解压后进入 bin 目录打开命令行窗口
命令行输入 wsdl2java -help
三、使用命令生成代码
替换 [xxx] 为你需要的参数
wsdl2java -encoding utf-8 -p [包名] -d [代码生成后存储的位置] [WebService XML文件位置或 wsdl 地址]
命令说明:
-p | 指定其wsdl的命名空间,也就是要生成代码的包名 |
---|---|
-d | 指定要产生代码所在目录 |
-client | 生成客户端测试web service的代码 |
-server | 生成服务器启动web service的代码 |
-impl | 生成web service的实现代码 |
-ant | 生成build.xml文件 |
-all | 生成所有开始端点代码:types,service proxy,,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file. |
等待命令执行完成后即可看到生成的代码。
常见问题
一、当调用需要账号密码怎么设置?
BindingProvider provider = (BindingProvider) port;
provider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY,"userName");
provider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,"passWord");
二、如果在请求接口时就需要账号密码怎么设置?
编写鉴权配置器
package com.example.playground.config;
import org.springframework.stereotype.Component;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
/**
* 描述: [xxx][权限验证]
*
* @version: 0_1
* @author: 朱安泰
* @date: 2022-05-07 20:42
**/
@Component
public class MyAuthenticator extends Authenticator{
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username","password".toCharArray());
}
}
在调用前设置鉴权配置类。
三、如何将报文输出在日志中?
package com.example.playground.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Set;
/**
*
* @version: 0_1
* @author: 朱安泰
* @date: 2022-09-25 10:32
**/
public class SoapMessageHandler implements SOAPHandler<SOAPMessageContext> {
private final Logger log = LoggerFactory.getLogger(SoapMessageHandler.class);
private final String TAG;
private static final String KEY_MSG_REQT = "请求SOAP报文";
private static final String KEY_MSG_RESP = "返回SOAP报文";
private static final String KEY_MSG_ERROR = "返回SOAP错误报文";
public SoapMessageHandler(String tag) {
TAG = tag;
}
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
context.getMessage().writeTo(outputStream);
} catch (SOAPException | IOException e) {
e.printStackTrace();
}
if ((boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)){
log.info("{}{}: {}", TAG, KEY_MSG_REQT, outputStream);
}else{
log.info("{}{}: {}", TAG, KEY_MSG_RESP, outputStream);
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
context.getMessage().writeTo(outputStream);
} catch (SOAPException | IOException e) {
e.printStackTrace();
}
log.error("{}{}: {}", TAG, KEY_MSG_ERROR, outputStream);
return false;
}
@Override
public void close(MessageContext context) {
}
}
//cxf 生成的代码中找到 Service 类
ZWSZQMK2CREATEMETHOD_Service service = new ZWSZQMK2CREATEMETHOD_Service(new URL("url..."));
//报文将在此处进行打印
service.setHandlerResolver(portInfo -> Lists.newArrayList(new SoapMessageHandler("PrintSoapMessageBLogic")));
测试用 wsdl 文件
LinkWS.xml