调用接口
有的公司调用接口很简单,给封装好的类传进去接口地址,返回就是一个JSON格式,直接用就可以了,有的公司需要自己写。
有多种方法可以调用接口,使用接口地址http://localhost:8080/helloservice/services/Helloservice?wsdl
为例子,这个接口是我自己写的。在第二种方法中有写怎么创建一个接口。
第一种,wsimport生成的调用
准备接口
-keep:是否生成java源文件
-d:指定.class文件的输出目录
-s:指定.java文件的输出目录
-p:定义生成类的包名,不定义的话有默认包名
-verbose:在控制台显示输出信息
-b:指定jaxws/jaxb绑定文件或额外的schemas
-extension:使用扩展来支持SOAP1.2
我们先拿到接口地址有了接口地址以后,使用命令wsimport -s src -d bin -keep 接口地址
例如以下:
wsimport -s src -d bin -keep http://localhost:8080/helloservice/services/Helloservice?wsdl
执行这个命令后,会在src下生成java文件,bin下生成class文件,src和bin是自己新建的文件夹,生成的信息就是接口的信息
调用接口
把生成的类复制粘贴到项目中,里面的内容都不用改
然后写测试类
public static void main(String[] args) throws RemoteException {
HelloserviceService hs=new HelloserviceService();
//拿到接口
Helloservice h=hs.getHelloservice();
//say是接口中的方法,想要其它方法,点它看都有什么方法就行
String say = h.say("aaaa");
System.out.println(say);
}
第二种,Eclipse创建Web Service Client
准备接口
新建一个web Project项目,新建的结构如下,没有任何内容
接下来新建一个要发布的类
写好以后右键项目,new—>other…,选择Web Service
完成以后,多了一个wsdl文件夹和wsdl文件,wsdl文件就是接口的信息
打开这个wsdl文件,往下翻,拿到接口的地址,拿到的地址要在尾部加上?wsdl
,到时候才能用
调用接口
已经拿到接口的地址了,随便新建一个项目
新建一个空的Java项目,接下来项目上面右键new—>other…,选择Web Service Client
在弹出框中填入接口信息,注意,要以wsdl结尾
点击完成后生成的结构如图
也是不用修改任何信息,直接写测试类
public static void main(String[] args) throws RemoteException {
HelloserviceProxy helloPxy = new HelloserviceProxy();
//获得接口
Helloservice service = helloPxy.getHelloservice();
//点出要调用的接口中的方法
String res = service.say("yyf");
System.out.println(res);
}
实例·调用天气服务
通过网络上发布的免费接口做个实例
这个不是通过接口地址调用接口了,是直接使用wsdl文件,因为说是这个网址是.net形式的,不能直接调用,要处理一下,删除里面的一些识别不了的标签<s:element ref="s:schema"/>
直接访问接口地址:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
打开以后另存为wsdl后缀的文件
编辑它,把所有的<s:element ref="s:schema"/>
删除,然后保存。
接下来直接用上面的第二种方法调用,不过不是输入地址了,而是直接选择修改好的wsdl文件,先把修改好的wsdl拖入项目
接下来项目上面右键new->other…->Web Service Client
选好以后确认,生成接口要用的信息
测试,这个接口有注释,需要传什么参数和返回什么参数都有写,到时候自己看就可以了,查一下北京的天气
其它
接口生成doc文档
选择要生成doc的java
接下来选择javadoc
会在你指定位置生成html,打开就可以
接口的代码生成jar来调用
先选中要打包的java,然后export
生成后直接导入调用
webservice通过wsdl生成客户端代码的几种方式
jdk自带的方式wsimport
jdk8可以使用,jdk11移除了,得用其它方式
命令名称 | 用法 举例 |
---|---|
-encoding | 指定编码格式 -encoding utf-8 |
-keep | 生成java源文件 -keep |
-d | 指定.class文件的输出目录 -d 路径 |
-s | 指定.java文件的输出目录, 此目录必须存在 -s 路径 |
-p | 定义生成类的包名,不定义的话有默认包名 -p 路径 |
-verbose | 在控制台显示输出信息 |
-b | 指定jaxws/jaxb绑定文件或额外的schemas |
-extension | 使用扩展来支持SOAP1.2 |
wsimport -s src -d bin -keep http://localhost:8080/helloservice/services/Helloservice?wsdl
Apache-cxf的wsdl2java
- 下载:https://archive.apache.org/dist/cxf/3.3.11/
- 解压到一个目录
- 配置环境变量
CXF_HOME
编辑path
%CXF_HOME%\bin
- 测试是否生效
- 生成代码
直接访问接口地址:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
另存为wsdl后缀的文件,识别不了<s:element ref="s:schema"/>
,编辑它,把所有的<s:element ref="s:schema"/>
删除,然后保存。
然后在想要生成代码的位置打开cmd,或者指定保存位置
wsdl2java -encoding utf-8 -d 生成文件的目录 wsdl文件地址或wsdl的url地址
C:\Users\HHH\Desktop\sql>wsdl2java -encoding utf-8 -p com.wzw.example -d ./ ./WeatherWS.wsdl
C:\Users\HHH\Desktop\sql>
生成成功
java请求wsdl
这个方法改一下wsdl地址,改一下SOAPAction方法名,改一下参数,直接运行
package com.example.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import javax.annotation.Resource;
public class GetEquipMsgUtils {
public static void main(String[] args) throws IOException {
//第一步:创建服务地址,也就是提供的WSDL的接口地址
URL url = new URL("http://localhost:8092/services/ims?wsdl");
//第二步:打开一个通向服务地址的连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//第三步:设置参数
//3.1发送方式设置:POST必须大写
connection.setRequestMethod("POST");
//3.2设置数据格式:content-type
connection.setRequestProperty("Content-Type", "text/xml");
//SOAPAction,固定参数,getKPIValue请求的方法名
connection.setRequestProperty("SOAPAction", "getKPIValue");
//3.3设置输入输出,因为默认新创建的connection没有读写权限,
connection.setDoInput(true);
connection.setDoOutput(true);
//第四步:组织SOAP数据,发送请求,
String soapXML = getXML();
//将信息以流的方式发送出去
OutputStream os = connection.getOutputStream();
os.write(soapXML.getBytes());
//第五步:接收服务端响应,打印
int responseCode = connection.getResponseCode();
if (200 == responseCode) {//表示服务端响应成功
//获取当前连接请求返回的数据流
InputStream is = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
int BUFFER_SIZE = 1024;
char[] buffer = new char[BUFFER_SIZE]; // or some other size,
int charsRead = 0;
while ( (charsRead = br.read(buffer, 0, BUFFER_SIZE)) != -1) {
sb.append(buffer, 0, charsRead);
}
/**
* 打印结果
*/
System.out.println("---" + sb.toString());
try {
//对返回的数据进行JSON格式化
System.out.println(xml2Json(sb.toString()));
} catch (Exception e) {
e.printStackTrace();
}
is.close();
isr.close();
br.close();
}
os.close();
}
//请求入参
public static String getXML(){
String soapXML = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://webservice.tcp.tmkj.com\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <web:getKPIValue>\n" +
" <!--Optional:-->\n" +
" <web:param><?xml version="1.0" encoding="gb2312"?><info><CorporationCode> </CorporationCode><Time></Time><api name="BusinessSystemOnlineNum"></api></info></web:param>\n" +
" </web:getKPIValue>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
return soapXML;
}
/**
* xml转json
*
* @param xmlStr
* @return
* @throws DocumentException
*/
public static JSONObject xml2Json(String xmlStr) throws DocumentException {
Document doc = DocumentHelper.parseText(xmlStr);
JSONObject json = new JSONObject();
dom4j2Json(doc.getRootElement(), json);
return json;
}
/**
* xml转json
*
* @param element
* @param json
*/
public static void dom4j2Json(Element element, JSONObject json) {
List<Element> chdEl = element.elements();
for(Element e : chdEl){
if (!e.elements().isEmpty()) {
JSONObject chdjson = new JSONObject();
dom4j2Json(e, chdjson);
Object o = json.get(e.getName());
if (o != null) {
JSONArray jsona = null;
if (o instanceof JSONObject) {
JSONObject jsono = (JSONObject) o;
json.remove(e.getName());
jsona = new JSONArray();
jsona.add(jsono);
jsona.add(chdjson);
}
if (o instanceof JSONArray) {
jsona = (JSONArray) o;
jsona.add(chdjson);
}
json.put(e.getName(), jsona);
} else {
if (!chdjson.isEmpty()) {
json.put(e.getName(), chdjson);
}
}
} else {
if (!e.getText().isEmpty()) {
json.put(e.getName(), e.getText());
}
}
}
}
}
问题
Illegal processing instruction target (“xml”); xml (case insensitive) is reserved by the specs.
请求webservice接口,参数要求为xml格式时,提示Illegal processing instruction target ("xml"); xml (case insensitive) is reserved by the specs.
,由于转义符号的原因,请求参数不能直接为xml格式。
- 原xml
<?xml version="1.0" encoding="gb2312"?>
<info>
<CorporationCode>地域代码1,地域代码2,地域代码3….</CorporationCode>
<Time>时间值</Time>
<api name="指标名称1"></api>
</info>
输入xml格式的参数时,首先需要添加<?xml version="1.0" encoding="UTF-8"?>(注意:这一行必须出现在第一行,并且需要顶格,前面没有任何空格或其他字符),使得输入参数符合xml标准;其次对于转义字符,需要进行改变。
- 改变后
<?xml version="1.0" encoding="gb2312"?>
<info>
<CorporationCode> < /CorporationCode>
<Time></Time>
<api name="BusinessUserRegNum"> < /api>
</info>
- 常用的一些转义字符
特殊符号 | 代码 |
---|---|
< | < |
> | > |
" | " |
& | & |
空格 | |
. | • |
Unexpected character ’ ’ (code 32) in content after ‘<’ (malformed start ele
标签内不能有空格< info>< / info>,不管是前面标签还是后面标签,都不能有空格
The driver has not received any packets from the server.
同一个项目中,有http接口和webservice接口,webservice五分钟一次,有请求进来,大概webservice接口运行一两天左右挂掉了,但是http正常,出现以下提示,分析原因为数据库连接数太多,连接没有关闭。改了部分代码,关闭connect,由一天挂掉一次,变成两天挂掉一次。发现是代码太多,有些漏掉了。
The driver has not received any packets from the server.
java.sql.SQLException: Connection reset
- 原因:
手写的jdbc连接释放,有些连接没有关闭,时间长了,数据库连接数太多,导致连不上,报错了。 - 解决:
使用mybatis进行数据库操作,交给mybatis管理。