Loading

使用 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.

等待命令执行完成后即可看到生成的代码。
image.png

常见问题
一、当调用需要账号密码怎么设置?

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());
    }
}

在调用前设置鉴权配置类。
image.png

三、如何将报文输出在日志中?

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

posted @ 2022-09-25 19:36  ANTIA11  阅读(1337)  评论(0编辑  收藏  举报