术语
- deal
SEI:Service Endpoint Interface
JAX:Java API for XML Web Servcie
JAX-WS RI:JAX-WS Reference Implementation
UDDI :Universal Description,Discovery and Integration
SOAP:Simple Object Access Protocol
WSDL:Web Services Description Language
SOA :Service Oriented Architecture ,中文一般理解为面向服务的架构,
JAXB : java xml binding, 是jax-rs jax-ws底层使用的对象与xml之间转换的工具
CXF :基于C#的SOA框架
WCF : 基于java的SOA框架
Web Service: 实现业务诉求
WSDL: 描述如何来使用SOAP 来调用Web 服务的, 通过 http://localhost:8080/webname/servicename?wsdl查看web服务说明。
SOAP: 简单对象访问协议,简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。接口规范
UDDI : 就是一个目录,只不过在这个目录中存放的是一些关于 Web 服务的信息而已
WebServices的特点:
1、WebServices 是自包含的。即在客户端不需要附加任何软件,只要客户机支持 HTTP 和XML 就 OK 了。
2、WebServices 是自我描述的。在客户端和服务端都不需要知道除了请求和响应消息的格式和内容外的任何事。
3、WebServices 是跨平台和跨语言的。客户端和服务端均可以在不同的平台和语言环境中实现,同时,不必为了支持 WebServices 而更改现有的代码。
4、WebServices 是基于开放和标准的。XML 和 HTTP 是WebServices 的主要技术基础,而 XML 和HTTP 早就成了业内标准了。
5、WebServices 是动态的。
6、WebServices 是可以组合的。也就是通过一个 WebService 访问另外一个 WebService 来达到组合的目的。通过组合 WebServices 便可以将简单的 WebServices 聚合成为实现更多复杂功能的复杂的服务。
7、WebServices 是松散耦合的。它完全解耦了客户端和服务端。
8、WebServices 提供编程访问的能力。换句话说,就是可以通过编写程序来访问Web 服务。
9、WebServices 是基于经过考验的成熟技术上构建的。比如 XML 和 HTTP。
10、WebServices 提供打包现有应用程序的能力。
11、WebServices 通过网络进行发布,查找和使用。
JAX-WS与JAX-RS区别是什么?
**JAX-WS:全称是JavaTM API forXML-Based Web Services
JAX-RS : 全称是 JavaTM API forRESTful Web Services**
一、JAX-WS与JAX-RS两者是不同风格的SOA架构。JAX-WS是针对WebService。而JAX-RS是针对RESTful HTTP Service。
二、JAX-WS以动词为中心,指定的是每次执行函数。JAX-RS名词为中心,每次执行的时候指的是资源。
三、JAX-WS面向消息的,每次请求的时候指定了请求的方法。 JAX-RS是面向资源的,每次请求都是对该资源进行操作,比如对资源的增删查改。
四、JAX-RS是JAVA EE6 引入的一个新技术。 JAX-RS是一个Java 编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建Web服务。
JAX-RS使用了Java SE5引入的Java标注来简化Web服务的客户端和服务端的开发和部署。
JAX-WS规范是一组XML web services的JAVA API,JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。
五、支持JAX-WS服务规范的框架有:CXF,Axis,Xfire。
支持JAX-RS服务规范的框架有:
CXF ——XFire和Celtix的合并
Jersey ——Sun公司的JAX-RS参考实现。
RESTEasy ——JBoss的JAX-RS项目。
Restlet——也许是最早的REST框架了,它JAX-RS之前就有了。
创建 Web Service方式
JAX-WS 2.0有两种创建Web Service的开发过程:自顶向下和自底向上。自顶向下方式指通过一个WSDL文件来创建Web Service;自底向上是从Java类出发创建Web Service。
自顶向下:
1、SEI(对应WSDL中的一个Web Service port,在Java中表现为一个接口);
2、SEI实现类;
3、WSDL和XSD文件;
自底向上:
1、声明某个类为@WebService,即将它声明为SEI实现类,然后对需要暴露的方法标注为@WebMethod;
2、运行wsgen命令生成其他所需文件;
3、发布Web Service;
注解说明
@javax.jws.WebService
该注解应用于类或者接口上面,该类便是一个对外访问WebService,默认情况里面所有的public方法都是可以对外提供访问,如果@WebServcie标注接口,那么该接口有一个专业名称SEI(ServiceEnpointInterface),该注解的属性如下:
name : 服务实现类的名称,wsdl上面 的名称
serviceName : 服务名称,wdsl上面的名称,缺省值为 Java 类的简单名称 + Service
portName: wsdl上面的名称,默认为发布实现者+Port
targetNamespace: 命名空间名称:发布webService服务的命名空间,此名称默认为包路径的“倒写”
endpointInterface : 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
wsdlLocation: 指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。
@javax.jws.WebMethod
该注解应用于方法上面,该注解的属性如下所示:
operationName: 指定与此方法相匹配的的名称。缺省值为 Java 方法的名称
operationName : 定义此操作的行为。对于 SOAP 绑定,此值将确定 头的值。缺省值为 Java 方法的名称。
exclude: 指定是否从 Web Service 中排除某一方法。缺省值为 false。
@javax.jws.Oneway
该注解应用于方法上
注释将一个方法表示为只有输入消息而没有输出消息的 Web Service 单向操作。
将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类
@javax.jws.WebParam
注释用于定制从单个参数至 Web Service 消息部件和 XML 元素的映射。
将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类;该注解属性如下所示:
name: 参数的名称。如果操作是远程过程调用(RPC)类型并且未指定partName属性,那么这是用于表示参数的 wsdl:part 属性的名称。如果操作是文档类型或者参数映射至某个头,那么 -name 是用于表示该参数的 XML 元素的局部名称。如果操作是文档类型、参数类型为 BARE 并且方式为 OUT 或 INOUT,那么必须指定此属性。
partName: 定义用于表示此参数的 wsdl:part属性的名称。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为BARE 时才使用此参数
targetNamespace : 指定参数的 XML 元素的 XML 名称空间。当属性映射至 XML 元素时,仅应用于文档绑定。缺省值为 Web Service 的 targetNamespace。
mode : 此值表示此方法的参数流的方向。有效值为 IN、INOUT 和 OUT。
header : 指定参数是在消息头还是消息体中。缺省值为 false。
@javax.jws.WebResult
注释用于定制返回值至 WSDL 部件或 XML 元素的映射。
将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类。该注解的属性如下:
name : 当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的 wsdl:part属性的名称。对于文档绑定,-name参数是用于表示返回值的 XML 元素的局部名。对于 RPC 和 DOCUMENT/WRAPPED 绑定,缺省值为 return。对于 DOCUMENT/BARE 绑定,缺省值为方法名 + Response。
targetNamespace : 指定返回值的 XML 名称空间。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为 BARE 时才使用此参数
header : 指定头中是否附带结果。缺省值为false
partName : 指定 RPC 或 DOCUMENT/BARE 操作的结果的部件名称。缺省值为@WebResult.name
@javax.jws.SOAPBinding
注释指定 Web Service 与 SOAP 消息协议之间的映射。
将此注释应用于客户机或服务器服务端点接口(SEI)上的类型或方法,或者应用于 JavaBeans 端点的服务器端点实现类。
方法级别的注释仅限于它可以指定的对象,仅当style 属性为 DOCUMENT 时才使用该注释。如果未指定方法级别的注释,那么将使用类型的@SOAPBinding 行为,该注解的属性如下所示:
style : 定义发送至 Web Service 和来自 Web Service 的消息的编码样式。有效值为DOCUMENT 和 RPC。缺省值为DOCUMENT。
use : 定义用于发送至 Web Service 和来自 Web Service 的消息的格式。缺省值为 LITERAL。ENCODED 在 Feature Pack for Web Services 中不受支持。
parameterStyle : 确定方法的参数是否表示整个消息体,或者参数是否是封装在执行操作之后命名的顶级元素中的元素。有效值为 WRAPPED 或 BARE。对于DOCUMENT 类型的绑定只能使用BARE 值。缺省值为 WRAPPED。
Demo目录视图
Calculator.java
package ws.test.service;
import javax.jws.WebService;
@WebService
public interface Calculator {
public int add(int a, int b);
public int multi(int a, int b);
}
CalculatorImpl.java
package ws.test.service.impl;
import javax.jws.WebService;
import ws.test.service.Calculator;
/**
* 这里WebService annotation里加了一个参数"endpointInterface",这个参数用来指定这个WebService的抽象服务接口,
* 例如此处如果不用"endpointInterface"指定接口,那么生成的WebService服务有三个操作"add","multi"和"minus",也就是定义在当前类中的方法集;
* 如果指定了endpointInterface,则只有"add","multi",即定义在Calculator中的方法集。
*
*/
@WebService(endpointInterface = "ws.test.service.Calculator")
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public int multi(int a, int b) {
return a*b;
}
public int minus(int a, int b) {
return a - b;
}
}
Endpoint发布服务
Server.java
import javax.xml.ws.Endpoint;
import ws.test.service.Calculator;
import ws.test.service.impl.CalculatorImpl;
public class Server {
public static void main(String[] args) {
// 部署方式一:
Endpoint.publish("http://localhost:8888/calculator", new CalculatorImpl());
}
}
浏览器访问:http://localhost:8888/calculator?wsdl
输入内容如下,部署成功:
访问http://localhost:8888/calculator?wsdl=1, 查看Calculator 接口说明。
web 容器发布服务
以Tomcat为例,首先编写sun-jaxws.xml文件并放到WEB-INF下
sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint name="catculatorImpl"
implementation="ws.test.service.impl.CalculatorImpl"
url-pattern="/ws/catculator" />
</endpoints>
web.xml, 添加listener和servlet(url-pattern要相同哦):
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>MyService</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyService</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>
将下面的jar包放入工程的WEB-INF/lib下
把工程导入tomcat,启动tomcat。
浏览器访问http://localhost:8080/ws/ws/catculator,如下图,部署成功。
访问http://localhost:8080/ws/ws/catculator?wsdl或者http://localhost:8080/ws/ws/catculator?wsdl=1可以看到相关接口说明。
客户端访问Service:
方法一,不需要生成客户端代码,客人比较喜欢这种方式:
Client.java
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import ws.test.service.Calculator;
public class Client {
public static void main(String[] args) throws Exception {
QName qName = new QName("http://impl.service.test.ws/", "CalculatorImplService");
URL url = new URL("http://localhost:8888/calculator?wsdl");
Service service = Service.create(url, qName);
Calculator calculator = service.getPort(Calculator.class);
System.out.println(calculator.add(10, 5));
}
}
方法二(wsimport生成客户端):
wsimport -keep http://localhost:8888/calculator?wsdl
将上诉代码复制到你的客户端项目里,使用下面的代码进行访问:
CalculatorImplService service = new CalculatorImplService();
Calculator calculator = service.getPortName();
System.out.println(calculator.add(1, 2));
方法三(创建一个Web Service Client的项目):
1、创建Web Service Client的项目
2、配置wsdl地址,并点击完成
使用下面的代码进行访问:
CalculatorImplService service = new CalculatorImplService();
Calculator calculator = service.getPortName();
System.out.println(calculator.add(1, 2));
这里有几点需要说明:
1、getPort()方法的参数:这个方法总是需要指定一个serviceEndpointInterface的类对象serviceEndpointInterface类需要加@WebService的annotation
2、serviceEndpointInterface的targetNamespace需要匹配对应的portType的namespace。默认是”http://包名/”,必要时需要定义@WebService的targetNamespace属性加以改变
3、serviceEndpointInterface的name总是需要匹配要调用的PortType的name。默认是类名,必要时需要指定@WebService的name属性加以改变
4、serviceEndpointInterface中需要有对应于要调用的operation的方法定义