时至今日。webservice这种远程调用技术都已经淘汰了,不排除有些老项目用但是非常少。笔者最近还就有个需求用到所以学习了一下。做个简单的总结
一、SOAP
soap是基于xml格式的消息交换协议。soap定义了信息交换的格式,它包含了一个重要的信封。使用信封来包装要传递的信息。xml里面都有一个命名空间叫做namespace来区分传递的信息;
二、wsdl
wsdl 是web service描述语言,它使用了xml对web Service描述,比如提供服务的方法、参数、返回值、数据类型等信息进行描述。
说完了就直接进入正题Java中怎么使用webservice进行开发 如果编写客户端和服务端的。
三 、服务端发布
便于测试我写个User对象:
public class User {
private int id;
private String name;
private Date birthday;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
那现在我定义一个普通的接口 UserService
public interface UserService {
public String sayHi (String name);
public String work (String work);
public User getUser (User user);
}
接口实现类 UserServiceImpl 标注了该@WebService注解的类的方法就变为webservice方法
/**
* 标注了该@WebService注解的类的方法就变为webservice方法
*/
@WebService
public class UserServiceImpl implements UserService {
@Override
public String sayHi(String name) {
return "Hi, " + name;
}
@Override
public String work (String work) {
return "He is working " + work;
}
@Override
public User getUser (User user) {
user.setName(user.getName() + "-service");
return user;
}
}
由此一个服务端的webService的方法就写完了,那我们现在需要把这个服务发布出去给怎么发布呢?
比如我可以选中普通的main方法启动endpoint 的 publish方法发布
public class Server {
public static void main(String[] args) {
//发布webservice
String wsAddress = "http://localhost:6868/01-ws-java-server/ws";
Endpoint endpoint = Endpoint.publish(wsAddress, new UserServiceImpl());
System.out.println("webservice发布成功:" + endpoint.isPublished());
}
}
如此我们就发布了这个webService 服务。
那么启动这个main方法之后我们可以浏览器访问我们发布的服务地址 + ?wsdl
http://localhost:6868/01-ws-java-server/ws?wsdl
那我就是上面这个地址了,得到的是一个wsdl在线文档。那么在开发中如果你是服务提供方你就只需要把这个路径告诉别人就行,这个在线文档大概长这样:
<!--
Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e.
--><!--
Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e.
--><definitions targetNamespace="http://impl.service.ws.wkcto.com/" name="UserServiceImplService"><types><xsd:schema><xsd:import namespace="http://impl.service.ws.wkcto.com/" schemaLocation="http://localhost:6868/01-ws-java-server/ws?xsd=1"/></xsd:schema></types><message name="sayHi"><part name="parameters" element="tns:sayHi"/></message><message name="sayHiResponse"><part name="parameters" element="tns:sayHiResponse"/></message><message name="work"><part name="parameters" element="tns:work"/></message><message name="workResponse"></message><message name="getUser"><part name="parameters" element="tns:getUser"/></message><message name="getUserResponse"><part name="parameters" element="tns:getUserResponse"/></message><portType name="UserServiceImpl"><operation name="sayHi"><input wsam:Action="http://impl.service.ws.wkcto.com/UserServiceImpl/sayHiRequest" message="tns:sayHi"/><output wsam:Action="http://impl.service.ws.wkcto.com/UserServiceImpl/sayHiResponse" message="tns:sayHiResponse"/></operation><operation name="work"><input wsam:Action="http://impl.service.ws.wkcto.com/UserServiceImpl/workRequest" message="tns:work"/><output wsam:Action="http://impl.service.ws.wkcto.com/UserServiceImpl/workResponse" message="tns:workResponse"/></operation><operation name="getUser"><input wsam:Action="http://impl.service.ws.wkcto.com/UserServiceImpl/getUserRequest" message="tns:getUser"/><output wsam:Action="http://impl.service.ws.wkcto.com/UserServiceImpl/getUserResponse" message="tns:getUserResponse"/></operation></portType><binding name="UserServiceImplPortBinding" type="tns:UserServiceImpl"><soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="sayHi"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="work"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="getUser"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation></binding><service name="UserServiceImplService"><port name="UserServiceImplPort" binding="tns:UserServiceImplPortBinding"><soap:address location="http://localhost:6868/01-ws-java-server/ws"/></port></service></definitions>
里面包含了这个服务里面的所有的webService方法。那我们现在简单解读一下这个文件的各个节点代表的是什么意思。开发中不懂也没关系会用就行。
1、targetNamespace 命名空间了 不是了具体你其实看看你的mapper文件的xml
2、service 整个webservice的服务信息,比如服务名,包括所有的服务
3、binding 定义每个服务接口的消息格式和协议细节。
4、portType 描述整个webService可以被执行的操作及相关信息
5、message 定义操作的一个或多个数据参数
6、types 定义webService使用的全部数据类型
四、客户端调用
那么刚刚说我们拿到别人的wsdl的地址之后怎么使用呢
我觉得第一个就是解析这个地址吧我最喜欢的一个方式:打开jdk的安装目录的bin目录下面有个wsimport.exe。我们在这个bin里面打开dos窗口输入下面的语句 -p 后面紧跟的是包名的路径
wsimport -encoding utf8 -keep -p com.wkcto.ws.stub -Xnocompile
http://localhost:6868/01-ws-java-server/ws?wsdl
wsimport 命令
-encoding 指定生成代码的编码格式
-keep 保存生成的代码
-p 指定包名
-Xnocompile 表示生成的代码不编译
解析得到一个:
把这个拷到你的项目里面。就可以引用了。去找这些文件当中的实现类被@WebServiceClient这个注解修饰的类
那么我们就可以开始调用了
你要是测试觉得麻烦就把我上面的birthday换成string就行我这里加了个工具类
package com.wkcto.ws.utils;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.Calendar;
import java.util.Date;
public class DateUtils {
/**
* 将Date类转换为XMLGregorianCalendar
*
* @param date
* @return
*/
public static XMLGregorianCalendar dateToXmlDate(Date date){
Calendar cal = Calendar.getInstance();
cal.setTime(date);
DatatypeFactory dtf = null;
try {
dtf = DatatypeFactory.newInstance();
XMLGregorianCalendar dateType = dtf.newXMLGregorianCalendar();
dateType.setYear(cal.get(Calendar.YEAR));
//由于Calendar.MONTH取值范围为0~11,需要加1
dateType.setMonth(cal.get(Calendar.MONTH)+1);
dateType.setDay(cal.get(Calendar.DAY_OF_MONTH));
dateType.setHour(cal.get(Calendar.HOUR_OF_DAY));
dateType.setMinute(cal.get(Calendar.MINUTE));
dateType.setSecond(cal.get(Calendar.SECOND));
return dateType;
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
return null;
}
/**
* 将XMLGregorianCalendar转换为Date
*
* @param cal
* @return
*/
public static Date xmlDate2Date(XMLGregorianCalendar cal){
return cal.toGregorianCalendar().getTime();
}
}
那我们开始调用 分三步吧都是固定的:
//1.创建一个webservice的客户端
UserServiceImplService userServiceImplService = new UserServiceImplService();
//2.获取远程服务接口对象
UserServiceImpl userService = userServiceImplService.getUserServiceImplPort();
//3.直接调用远程服务接口对象的方法
String hi= userService.sayHi("张三丰");
System.out.println(hi);
String work = userService.work("Java");
System.out.println(work);
User user = new User();
user.setId(100);
user.setName("张无忌");
就可以了。
五、开发总结
总结不到的地方可以提出来可能很多人会问用web spring整合webservice的客户端怎么写之类的,其实就是一个服务发布的问题 主要的是你需要将你想暴露的接口方法的实现类使用@WebService 注解修饰。调用那就一定是我上面的调用步骤肯定是可以的。
额,没写到的欢迎补充!!!