soap cxf 客户端 超时 404等问题

许多老系统都使用wsdl为服务,特别是.net系统下面介绍java调用wsdl的示例

1、下载cxf客户端
2、./wsdl2java -encoding utf-8 -p 包名 -d . -client http://xx.xx.xx.xx/service/?wsdl生成代码
3、添加pom

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.1.10</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.1.10</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>${guava.version}</version>
</dependency>

假如:ServiceSoap是我们生成的Soap文件java代码如下


@Slf4j
@Component
public class WsdlServiceConfig {

    @Value("${wsdl.reloadTime:1800}")
    private Integer reloadTime; //重新加载时间

    @Value("${wsdl.connectionTimeout:10000}")
    private Integer connectionTimeout;

    @Value("${wsdl.receiveTimeout:10000}")
    private Integer receiveTimeout;

    private Cache<String, ServiceSoap> cache = null; //创建本地缓存,可以用ConcurrentHashMap代替

    @PostConstruct
    public void init() {
        cache = CacheBuilder.newBuilder()
                .maximumSize(500)
                .initialCapacity(20)
                .expireAfterWrite(getSecond(), TimeUnit.SECONDS) //秒超时
                .concurrencyLevel(20)
                .build();
    }


    private int getSecond() {
        if (reloadTime == null) {
            log.info("config default is 30 min");
            return 60 * 30;
        }
        log.info("WsdlServiceConfig config time value is {} second", reloadTime);
        return reloadTime;
    }

    public ServiceSoap getWsdlService(String cacheKey, String address) {
        ServiceSoap serviceSoap= cache.getIfPresent(cacheKey);
        if (serviceSoap== null) {
            serviceSoap= this.create(siteUser, address);
            this.setTimeoutTime(serviceSoap);
            cache.put(cacheKey, serviceSoap);
        }
        return serviceSoap;
    }

    private synchronized ServiceSoap create(String address) {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(ServiceSoap.class);
        factory.setAddress(address);
        factory.getOutInterceptors().add(new MyHeader()); //自己的头
        factory.getOutInterceptors().add(new LoggingOutInterceptor());
        return (ServiceSoap) factory.create();
    }

    private void setTimeoutTime(Object service) {
        try {
            Client proxy = ClientProxy.getClient(service);
            HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
            HTTPClientPolicy policy = new HTTPClientPolicy();
            policy.setConnectionTimeout(connectionTimeout); // 请求超时
            policy.setReceiveTimeout(receiveTimeout); //读取超时
            conduit.setClient(policy);
        } catch (Exception e) {
            log.error("wsdl setTimeoutTime", e);
        }
    }

}

MyHeader代码

public class MyHeader extends AbstractSoapInterceptor {

    private String siteUser;

    public AddSoapHeader(String siteUser) {
        super(Phase.WRITE); // 执行点。有很多可选
        this.siteUser = siteUser;
    }
	
    @Override
    public void handleMessage(SoapMessage soapMessage) {
        QName qName = new QName("SiteUser");
        Document doc = DOMUtils.createDocument();
        Element root = doc.createElementNS("http://tempuri.org", "SiteUser");
        root.setTextContent(siteUser);
        SoapHeader header = new SoapHeader(qName, root);
        List<Header> headers = soapMessage.getHeaders();
        headers.add(header); //soap添加头部验证
    }

}

以上为正常简单的soap配置就完成啦

如果对方是endpoint形式:
第一种方式根据wsdl方式分析地址

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ServiceSoap.class); //生成的代理类
factory.setWsdlURL(wsdl);//wsdl地址
factory.setServiceName(new QName("http://tempuri.org/", "Bill")); //主要看你wsdl描述
factory.setEndpointName(new QName("http://tempuri.org/", "basic")); //主要看你wsdl描述
factory.getOutInterceptors().add(new LoggingOutInterceptor());
return (T) factory.create();

serviceName 一般cxf生成的代码里都有可以自行查看在这里插入图片描述

endpoint地址如下如果调用404一般都是endpoint设置的不对,检查自己的wsdl文件查看
endpoint地址

第二种方式直接写调用地址,不是wsdl地址。

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ServiceSoap.class); //生成的代理类
factory.setAddress("http://xxx.xxx/service/Basic");//调用地址 也就是endpoint地址 根据上图填写
factory.setServiceName(new QName("http://tempuri.org/", "Bill")); //主要看你wsdl描述
factory.setEndpointName(new QName("http://tempuri.org/", "basic")); //主要看你wsdl描述
factory.getOutInterceptors().add(new LoggingOutInterceptor());
return (T) factory.create();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot集成CXF时,可以使用CXF提供的工具类org.apache.cxf.jaxws.JaxWsProxyFactoryBean创建WebService客户端,并使用该客户端调用WebService接口方法。生成的SOAP请求包可以通过在客户端代码中添加日志输出或使用抓包工具进行捕获。 以下是一个示例: 1. 定义WebService接口 ```java package com.example.demo; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; @WebService public interface HelloWorld { @WebMethod String sayHello(@WebParam(name = "name") String name); } ``` 2. 创建WebService客户端 ```java package com.example.demo; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; public class HelloWorldClient { public static void main(String[] args) { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(HelloWorld.class); factory.setAddress("http://localhost:8080/helloWorld"); HelloWorld helloWorld = (HelloWorld) factory.create(); String result = helloWorld.sayHello("World"); System.out.println(result); } } ``` 在以上代码中,通过JaxWsProxyFactoryBean创建了一个HelloWorld接口的代理对象,并指定了WebService的地址。调用sayHello方法后,将结果打印到控制台。 3. 查看SOAP请求包 可以通过在客户端代码中添加日志输出或使用抓包工具进行捕获,例如使用Wireshark进行抓包,然后在过滤器中设置“http.request.method == POST && tcp.port == 8080”进行过滤,即可查看请求数据包。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值