首先,这篇文章主要是用来做一个记录,方便以后使用,所以不会有太多关于webService以及wsdl的一些原理上的讲解,主要是为了解决实际问题,即:如何生成webService客户端去调用服务端,以及当服务端需要进行账号密码登录时,我们该如何模拟登录,来继续调用里面的接口。
主要是因为发现网上关于生成客户端以及调用的文章确实有很多,但是只要一涉及到服务端有账号密码的问题的解决方案就是少之又少,真正找到的有无法使用,所以才写这篇博客希望可以帮助同学们节省一些时间。好了,废话不多说了,直接上操作流程
1.客户端生成
首先,我们来生成客户端,因为此篇文章主要是解决服务端有账号密码的情况,所以咱们直接以有账号密码的服务端url来进行讲解和说明,首先一般的各种生成工具对直接输入账号密码生成客户端支持貌似都并不是很好(至少本人一直没有成功,也可能是操作问题)。所以,我会使用手动访问将其xml下载到本地进行本地文件的导入。
1.导出wsdl的xml文件
1.1 访问url,输入账号密码
1.2 进入后我们在页面右键另存为,将xml文件存到我们桌面,并将其后缀改为wsdl.
1.3 生成客户端
我这里使用的是idea自带的插件,网上也有很多基于dos的生成客户端的工具,自行选择即可。
首先,在要生成客户端的包下点击右键,选择WebService->Generate Java Code From Wsdl
生成后如下图所示
2.调用
正常情况下,如果服务端未设置账号和密码,其实我们已经可以进行调用,代码如下
public class cs {
public static void main(String[] args) {
ISysNotifyTodoWebServiceService is = new ISysNotifyTodoWebServiceService();
ISysNotifyTodoWebService iSysNotifyTodoWebService = is.getISysNotifyTodoWebServicePort();
NotifyTodoSendContext context = new NotifyTodoSendContext();
context.setSubject("测试待办webservice~~~");
context.setLink("http://news.sina.com.cn/");
context.setType(2);
context.setKey("sinaNews");
context.setModelId("123456789");
context.setTargets("{\"Id\":\"12fe2de141b7b97b32d1af34204a9f54\"}");
try {
NotifyTodoAppResult notifyTodoAppResult = iSysNotifyTodoWebService.sendTodo(context);
System.out.println(notifyTodoAppResult);
} catch (Exception_Exception e) {
e.printStackTrace();
}
}
}
运行结果如下
报错401,其实我们在访问wsdl的url时如果不输入账号密码也会给我们报401,所以证明我们的账号密码并没有被设置,那我们现在需要的就是设置账号密码,但问题是,我们到底要在哪里设置账号密码。不卖关子了,核心代码如下。
static {
java.net.Authenticator.setDefault(new java.net.Authenticator() {
@Override
protected java.net.PasswordAuthentication getPasswordAuthentication() {
return new java.net.PasswordAuthentication("账号",
"密码".toCharArray());
}
});
}
运行结果如下
这次访问成功,证明我们的账号密码呗设置好了,问题是解决了,但是核心问题到底在哪?这个账号密码到底是什么原理设置到了什么地方才让我们通过了验证?
3.HTTP基本认证(Basic Authentication)
其实webService设置了账号密码的流程是使用了Basic Authentication,我们所设置的账号密码其实会被以key:value经过basic64计算成字符串写到request头中。不相信?我们来看一下我们访问的wsdl路径的requestHeader
我们会看到头里有个Authorization的key, value值为我们不知道的一个字符串,那我们来试一下自己讲这个配置写入到头中,看看是否能跳过登录。
3.1 连接测试
我们先随便找个网上base64在线加密工具将我们的账号密码以key:value的形式进行加密,我们发现转换出来的串和我们刚才看到的串是一样的,如下图所示。接下来我们来将串写入到我们的头中,看是否生效
我们以访问刚才的wsdl链接为例,我们先不添加Authorization的串让其报错
package com.wsdltwo.cs;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by beyondLi
* Date 2018/1/18
* Desc .
*/
public class ClientCs {
public static void main(String[] args) {
URL url;
InputStream is = null;
StringBuffer sb = new StringBuffer();
URLConnection urlConn;
HttpURLConnection htcon;
try {
url = new URL("你的URL");
urlConn = url.openConnection();
/**
* 注释掉添加串,报401
*/
//urlConn.setRequestProperty("Authorization", "Basic " + "Ymd5X3pjeXEwMTo4MGQ2MDIwYzc3OTI0NzA2YTU0MGU0NTI2YzIwODk2NA==");
htcon = (HttpURLConnection) urlConn;
is = htcon.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int numCharsRead;
char[] charArray = new char[1024];
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
System.out.println(url.getAuthority());
System.out.println("sb: "+sb);
} catch (IOException e) {
e.printStackTrace();
}
}
}
效果如图
接下来我们将上面代码注释的设置打开,在此运行代码,效果如图,成功连接
好了,核心原因就讲解到这里,解决实际问题的话遵循1和2的步骤进行设置即可,后面的代码是为了可以让各位同学可以更好的看到到底我们1,2中的步骤底层都做了哪些操作。