WebService在java中的简单应用
一、WebService简介
1、什么是WebService
WebService即web服务,w3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计。Web Service服务通常被定义为一组模块化的API,它们可以通过网络进行调用,来执行远程系统的请求服务。简而言之,WebService就是一种跨编程语言和跨操作系统平台的远程调用技术
2、WebService技术支持
(1)XML和XSD
XML(Extensible Markup Language) 扩展性标记语言,XML主要的优点在于它既与平台无关,又与厂商无关。XML是由万维网协会(W3C)创建,W3C制定的XML SchemaXSD 定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型。Web Service平台是用XSD来作为数据类型系统的。为了符合Web Service标准,所有你使用的数据类型都必须被转换为XSD类型。如想让它使用在不同平台和不同软件的不同组织间传递,还需要用某种东西将它包装起来。这种东西就是一种协议,如 SOAP。
(2)SOAP
SOAP (Simple Object Access Protocol):简易对象访问协议,它是用来来描述传递数据的格式的。SOAP是基于HTTP的,发送请求和接收结果时,数据内容是采用XML格式封装,然后加上特定的HTTP消息头,以说明 HTTP消息的内容格式。HTTP消息头加上XML数据就是SOAP协议。所以可以认为SOAP = HTTP+XML数据。
(3)WSDL
WSDL(WebService Description Language)WebService描述语言。它用来描述如何访问具体的接口,通过xml形式说明服务地址以及如何调用。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。 WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。
(4)UDDI
UDDI(Universal Description Discovery and Integration):通用描述、发现及整合。用来管理、分发、查询webService。UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
二、WebService Java代码实现
1、WebService服务端代码实现
(1)创建简单java工程。
(2)创建服务接口SEI(Service Endpoint Interface),SEI在WSDL中就是portType,在java中其实就是普通接口
/** * * @author dmf * WebService 服务接口SEI(Service Endpoint Interface),在wsdl中就是portType * */ @WebService public interface UserService { public String saveUserInfo(String name,int age); public String getUserInfoById(String id); }
(3)创建接口的实现类,加上@WebService注解
注意:
1、给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。
2、如果希望某个方法不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。
3、如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。protected、private、final、static方法不能对外公开
@WebService //@WebService注解表示该类是一个服务类,需要发布其中的public的方法 public class UserServiceImpl implements UserService{ @Override public String saveUserInfo(String name, int age) { System.out.println("姓名:"+name+" 年龄:"+age); return "success"; } @Override public String getUserInfoById(String id) { // TODO Auto-generated method stub System.out.println("用户id:"+id); return "张三"; } }
(4)发布服务
public class UserServicePublish { public static void main(String[] args) { // WebService的发布地址,地址格式为:http://ip:端口号/xxxx,IP为本机IP地址 String address = "http://localhost:8888/UserServer/Webservice"; // 使用Endpoint类提供的publish方法发布WebService,发布时要保证使用的端口号没有被其他应用程序占用,第二个参数为是服务实现类 Endpoint.publish(address, new UserServiceImpl()); System.out.println("webservice成功发布!"); //验证是否发布成功:直接把address复制到浏览器访问,或者用address?wsdl也可以 } }
(5)验证是否发布成功。
在浏览器地址栏输入http://localhost:8888/UserServer/Webservice或者http://localhost:8888/UserServer/Webservice?wsdl 即可
如果是web项目的话,可以在servlet或者监听器中的初始化方法中编写发布代码用来发布WebService服务
2、WebService客户端代码实现
Webservice服务发布后,我们要怎样调用呢?下面我们来试一下编写WebService客户端来调用WebService服务
使用jdk自带工具wsimport.exe生成客户端代码(bin目录下)
(1)生成客户端代码。打开cmd,输入wsimport命令(不清楚的可以输入wsimport -help命令查看此命令详情)
示例:wsimport -s . http://localhost:8888/UserServer/Webservice?wsdl。此命令为在当前目录生成客户端代码。
将生成的代码放入客户端程序中
离线解析:
当在没有网络的情况下开发客户端时,我们可以将wsdl保存为xml文件放在本地然后再解析。
(2)编写测试类
public class UserServiceClient { public static void main(String[] args) { //创建发服务视图,视图类名称是wsdl的service标签的name属性的值 UserServiceImplService factory = new UserServiceImplService(); //根据视图对象获取服务实现接口,名称是wsdl的portType标签的name属性值。UserServiceImpl是接口,不是类 UserServiceImpl userImpl = factory.getUserServiceImplPort(); //也可以使用下面这种service编程调用方式 //UserServiceImplService是自动生成的UserServiceImplService类的名称 //Service service = Service.create(new URL("http://localhost:8888/UserServer/Webservice?wsdl") // , new QName("http://impl.service.server2.dmf.com/","UserServiceImplService")); //UserServiceImpl userImpl = service.getPort(UserServiceImpl.class); //调用方法,wsdl的ortType标签下operation标签的name值 String userName = userImpl.getUserInfoById("123"); System.out.println("根据id获取到的用户姓名为:"+userName); String result = userImpl.saveUserInfo("李四", 19); System.out.println("用户信息保存结果为:"+result); }
(3)客户端其他实现方式
使用HttpURLConnection调用方式,这中方式编写客户端,不用工具生成代码,但是需要自己封装请求,解析响应数据。
这部分参考的是这篇博客里的:https://www.geek-share.com/detail/2711976878.html
/** * * @author dmf HttpURLConnection调用 */ public class UserServiceClient1 { public static void main(String[] args) throws IOException{ // 第一步:创建服务地址,不是WSDL地址 URL url = new URL("http://localhost:8888/UserServer/Webservice"); // 第二步:打开一个通向服务地址的连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 第三步:设置参数 // 3.1发送方式设置:POST必须大写 connection.setRequestMethod("POST"); // 3.2设置数据格式:content-type connection.setRequestProperty("content-type", "text/xml;charset=UTF-8"); // 3.3设置输入输出,因为默认新创建的connection没有读写权限, connection.setDoInput(true); connection.setDoOutput(true); // 第四步:组织SOAP数据,发送请求 String soapXML = getSOAPXML(123); OutputStream os = connection.getOutputStream(); os.write(soapXML.getBytes()); // 第五步:接收服务端响应,打印 int responseCode = connection.getResponseCode(); if (200 == responseCode) {// 表示服务端响应成功 InputStream is = connection.getInputStream(); // 将字节流转换为字符流 InputStreamReader isr = new InputStreamReader(is, "utf-8"); // 使用缓存区 BufferedReader br = new BufferedReader(isr); StringBuilder sb = new StringBuilder(); String temp = null; while (null != (temp = br.readLine())) { sb.append(temp); } System.out.println(sb.toString()); is.close(); isr.close(); br.close(); } os.close(); } // 将数据拼接成SOAP需要的格式,这是调用getUserInfoById方法时封装的方法,调用其他方法得另外重新封 //装 public static String getSOAPXML(int id){ String soapXML="<?xml version=\"1.0\" ?>" +"<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<S:Body><ns2:getUserInfoById xmlns:ns2=\"http://impl.service.server2.dmf.com/\">" +"<arg0>"+id+"</arg0></ns2:getUserInfoById></S:Body></S:Envelope>"; return soapXML; } }
返回结果:
<?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:getUserInfoByIdResponse xmlns:ns2="http://impl.service.server2.dmf.com/"> <return>张三</return> </ns2:getUserInfoByIdResponse> </S:Body> </S:Envelope>
返回结果是一个SOAPxml格式文件,要想获取返回值,还需要解析这个xml文件。查看数据格式方法:
使用eclipse自带的TCP/IP Monitor工具。
1、打开这个工具,Window》Show View》Other然后搜索TCP/IP Monitor。
2、设置要代理的服务器
第一个参数是代理端口,例如:1234
第二个参数是被代理服务器的地址,WebService服务ip。
第三个参数是被代理服务器的端口,WebService服务端口
第四个参数要选择为TCP/IP
3、启动代理,然后用客户端访问WebService服务
请求参数
GET /UserServer/Webservice?wsdl HTTP/1.1 User-Agent: Java/1.7.0_51 Host: localhost:1234 Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive POST /UserServer/Webservice HTTP/1.1 Accept: text/xml, multipart/related Content-Type: text/xml; charset=utf-8 SOAPAction: "http://impl.service.server2.dmf.com/UserServiceImpl/getUserInfoByIdRequest" User-Agent: JAX-WS RI 2.2.4-b01 Host: localhost:1234 Connection: keep-alive Content-Length: 224 <?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getUserInfoById xmlns:ns2="http://impl.service.server2.dmf.com/"><arg0>123</arg0></ns2:getUserInfoById></S:Body></S:Envelope>
响应参数:
HTTP/1.1 200 OK Transfer-encoding: chunked Content-type: text/xml;charset=utf-8 Date: Sat, 29 Dec 2018 09:51:15 GMT b69 <?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --><definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://impl.service.server2.dmf.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.service.server2.dmf.com/" name="UserServiceImplService"> <types> <xsd:schema> <xsd:import namespace="http://impl.service.server2.dmf.com/" schemaLocation="http://localhost:1234/UserServer/Webservice?xsd=1"></xsd:import> </xsd:schema> </types> <message name="saveUserInfo"> <part name="parameters" element="tns:saveUserInfo"></part> </message> <message name="saveUserInfoResponse"> <part name="parameters" element="tns:saveUserInfoResponse"></part> </message> <message name="getUserInfoById"> <part name="parameters" element="tns:getUserInfoById"></part> </message> <message name="getUserInfoByIdResponse"> <part name="parameters" element="tns:getUserInfoByIdResponse"></part> </message> <portType name="UserServiceImpl"> <operation name="saveUserInfo"> <input wsam:Action="http://impl.service.server2.dmf.com/UserServiceImpl/saveUserInfoRequest" message="tns:saveUserInfo"></input> <output wsam:Action="http://impl.service.server2.dmf.com/UserServiceImpl/saveUserInfoResponse" message="tns:saveUserInfoResponse"></output> </operation> <operation name="getUserInfoById"> <input wsam:Action="http://impl.service.server2.dmf.com/UserServiceImpl/getUserInfoByIdRequest" message="tns:getUserInfoById"></input> <output wsam:Action="http://impl.service.server2.dmf.com/UserServiceImpl/getUserInfoByIdResponse" message="tns:getUserInfoByIdResponse"></o 1bb8b utput> </operation> </portType> <binding name="UserServiceImplPortBinding" type="tns:UserServiceImpl"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding> <operation name="saveUserInfo"> <soap:operation soapAction=""></soap:operation> <input> <soap:body use="literal"></soap:body> </input> <output> <soap:body use="literal"></soap:body> </output> </operation> <operation name="getUserInfoById"> <soap:operation soapAction=""></soap:operation> <input> <soap:body use="literal"></soap:body> </input> <output> <soap:body use="literal"></soap:body> </output> </operation> </binding> <service name="UserServiceImplService"> <port name="UserServiceImplPort" binding="tns:UserServiceImplPortBinding"> <soap:address location="http://localhost:1234/UserServer/Webservice"></soap:address> </port> </service> </definitions> 0 HTTP/1.1 200 OK Transfer-encoding: chunked Content-type: text/xml; charset=utf-8 Date: Sat, 29 Dec 2018 09:51:15 GMT 5e <?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body> 99 <ns2:getUserInfoByIdResponse xmlns:ns2="http://impl.service.server2.dmf.com/"><return>张三</return></ns2:getUserInfoByIdResponse></S:Body></S:Envelope> 0
三、其他
1、WSDL文件解析
前面我们讲过WSDL是web服务描述语言,相当于webservice服务使用说明书,WSDL是随服务发布成功,自动生成,无需编写。
service标签:整个WebService的服务视图,包括了所有的服务端口。
bind标签:定义每个端口的数据格式规范和具体协议。
portType标签:服务端点,描述 web service可被执行的操作方法,以及相关的消息,通过binding指向portType。
message标签:定义一个操作(方法)的数据参数(可有多个参数)。
types标签:定义WebService的全部数据类型。
阅读顺序从下往上阅读。不同语言实现wsdl可能会有少许不同,例如:java和.net生成的wsdl有少许差别。
2、SOAP详解
SOAP即简单对象访问协议,他是使用http发送的XML格式的数据,它可以跨平台,跨防火墙,SOAP不是webservice的专有协议,邮件SMPT传输协议也用这个。
SOAP结构:
必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
可选的 Header 元素,包含头部信息
必需的 Body 元素,包含所有的调用和响应信息
可选的 Fault 元素,提供有关在处理此消息所发生错误的信息
SOAP目前有1.1和1.2两个版本,目前大多数使用的是1.1版本。区别:
命名空间:
SOAP1.1命名空间:
xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/ “
SOAP1.2命名空间:
xmlns:soap="http://www.w3.org/2003/05/soap-envelope“
请求头:
SOAP1.1存在SOAPAction的请求头。
SOAP1.2没有SOAPAction的请求头
SOAP1.1只可以绑定到HTTP协议,而SOAP1.2除了HTTP协议之外还支持SMTP绑定。如果服务端使用1.1,那么客户端只能使用1.1,但服务端使用1.2,那么客户端可以使用1.1或1.2,优先用1.2。
3、WebService和Socket区别
1、Socket是基于TCP/IP的,WebService是基于HTTP的。
2、Socket通过流传输,不支持传输对象。WebService 支持面向对象,WebService将对象进行序列化后通过流传输。
3、Socket适用于高性能大数据的传输,传输的数据需要手动处理,socket通信的接口协议需要自定义。WebService适用于没有性能要求情况下且数据量较小的情况下,如果webservice开发大并发的应用,webservice依靠web容器提高并发数。
- java调用远程webservice 简单应用
- Java发布一个简单 webservice应用 并发送SOAP请求
- Java发布一个简单 webservice应用 并发送SOAP请求
- JAVA 应用简单破解---类库提前加载
- 无废话的基于axis2+tomcat架构webservice 的java 应用流程
- .net 调用java WebService简单教程
- JAVA 应用简单破解---类库提前加载
- JAVA 简单的正则表达式应用
- 类加载器的方式管理资源和配置文件/JavaBean/重构_内省的简单应用
- Java WEB之Servlet学习之路(一)一个最简单的Servlet应用
- java图像界面开发简单实例-JPanel应用
- 利用Java编写简单的WebService实例
- java.security.*包下MessageDigest类的简单应用 MD5加密
- Java反射学习简单应用
- java构建简单的CORBA应用
- Java调用WebService服务,简单好用,实例讲解
- java(j2ee)应用-简单自定义标签开发全过程----之一(Inber)——JAVA夜未眠
- java中用Axis开发webservice的简单实例
- java图像界面开发简单实例-Graphics2D、Rectangle2D、Ellipse2D、Line2D的简单应用
- webservice delphi客户端 java服务器端 传输简单和复杂对象 小demo