天天看点

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生成的代码里都有可以自行查看

soap cxf 客户端 超时 404等问题

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

soap cxf 客户端 超时 404等问题

第二种方式直接写调用地址,不是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();
           

继续阅读