欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

soap cxf 客户端 超时 404等问题

程序员文章站 2022-05-18 15:01:33
...

许多老系统都使用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();