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生成的代码里都有可以自行查看
endpoint地址如下如果调用404一般都是endpoint设置的不对,检查自己的wsdl文件查看
第二种方式直接写调用地址,不是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();