月初导师给了份差事给我,让我写一个调用webservice接口的功能,刚好自己这边有webservice的学习资料,就先看了下,大致了解了.发布服务之后可以生成一个wsdl文件,通过jdk自带的wsimport命令可以直接生成客户端代码.
wsimport -s /路径/ -p /包名/ http://localhost/example/HelloWorld?wsdl
类似如此的命令,wsdl既可以是文件,也可以是网上的链接.
查看下结构
根据类型,去掉class文件,快速写个客户端.
wsdl文档是从下往上读的,先根据Service的名称创建service,然后根据port的名称创建接口.最后根据operation的名称调用接口的方法.实现webservice接口的调用,服务端也正常输出了Hello World,当然这只是最简单的demo案例.
一开始打算写在公司的项目里面,但转念一想是一个独立的功能,所以准备快速搭建一个环境.Spring Boot是个不错的选择.虽然对Spring Boot还不是特别熟,但至少简化了配置.要先从oracle数据库中读取数据,添加到soap报文中,然后还有认证头信息.最后如果调用接口成功,要在数据库中的returndate中返回当前时间.
一开始没有底,从来没有写过.在网上一直找如何添加认证头信息.找了很久发现CXF框架可以通过添加拦截器的方式,进行认证.瞎鼓捣了好久,总算是写出了初版.这里就要吐槽一下了,项目方部署项目竟然全都是内网.在现场的大佬说,就连内网访问服务器都要通过远程.真是晕.服务器上还有多个版本的jdk以及tomcat,所幸,有个tomcat8.0能跑.部署到测试服务器之后.实施说webservice访问的接口地址要做成可配置,定时任务也要做成可配置.当时脑子是懵的,cxf自动通过wsdl生成客户端,然后进行修改.没有涉及到地址之说,因为wsdl上有个soap:address 他的值就是暴露给外界的访问地址.
后面我使用服务器上的soapui进行测试发现给的wsdl文件自带的地址根本没有进行头信息验证,信息验证错误也是可以通过的,然后使用他们给的地址进行soap请求,发现对头信息进行了校验..又进入了懵逼状态.
思考了许久,后面想到soap请求本质上其实就是http+xml,那么直接将请求内容通过拼串的方式用post请求发送.于是又开始查资料,带内容发送http请求的工具类.找了许久有个apache的commons-httpclient包.再查下去发现这个已经停止开发了,转向了新的项目httpcomponents-httpclient,在maven中加上依赖后,查阅文档 开始.
@Value("${url}")
private String url;
@Autowired
private EAIResultService eaiResultService;
@RequestMapping("/test")
public String test() throws IOException {
//出现异常的次数
int count = 0;
//是否全部调用成功
boolean flag = true;
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
CloseableHttpClient client = httpClientBuilder.build();
HttpPost post = new HttpPost(url);
List<EAIResult> eaiResults = eaiResultService.selectAll();
for (EAIResult result : eaiResults) {
String sb = String.valueOf(getHeader()) + getBody(result);
StringEntity entity = new StringEntity(sb);
entity.setContentType("\"text/xml; UTF-8\"");
post.setEntity(entity);
CloseableHttpResponse execute = client.execute(post);
int statusCode = execute.getStatusLine().getStatusCode();
if (statusCode != 200) {
count += 1;
flag = false;
}
}
if (flag) {
System.out.println("webservice调用成功");
return "success";
} else {
System.out.println("有" + count + "条记录调用webservice出现问题");
return "failed";
}
}
贴一下调用接口的http的方法.要注意的是请求体里面的ContentType一定要设置为text/xml;utf-8,否则会返回415编码错误.
url是在Spring Boot的配置文件里面写好的
连接池,依旧使用的是我最喜欢的Druid,阿里的东西就是好用 嘻嘻~
需要注意的是Spring Boot因为内置tomcat,所以要以war包的形式部署在服务器上需要在入口添加重写configure方法.
@SpringBootApplication
@MapperScan("com.mingcloud.eai.dao")
public class EaiApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(EaiApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(EaiApplication.class);
}
}
在maven依赖中也要添加,并且修改项目的packaging为war,Spring Boot默认的打包方式是jar.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
然后就是打成war包,传到他们的服务器上,部署到tomcat上.
说下使用的定时器.其实是一个类实现了Runable,然后在线程中死循环调用,在循环中对线程进行sleep操作. : p
这次功能做完,对webservice算是登堂入室了.收益颇丰.还是很喜欢这种感觉,像是高中时候做数学题的感觉.23333