JAX-WS教程

时间:2020-02-23 14:35:17  来源:igfitidea点击:

欢迎使用JAX-WS教程。
Web服务在客户端-服务器模型上工作,它们通过网络进行通信。
服务器端组件提供服务所在的端点URL,客户端应用程序可以调用不同的方法。

Web服务有两种类型:

  • SOAP Web服务
  • 宁静的Web服务

JAX-WS教程

在本JAX-WS教程中,我们将使用JAX-WS创建基于SOAP的Web服务。
但是首先,我们将介绍SOAP Web服务中使用的一些专业术语。

肥皂

SOAP代表简单对象访问协议。
SOAP是用于设计和开发Web服务的基于XML的行业标准协议。
由于它基于XML,因此与平台和语言无关。
因此,我们的服务器可以基于JAVA,客户端可以基于.NET,PHP等,反之亦然。

WSDL

WSDL代表Web服务描述语言。
WSDL是基于XML的文档,提供有关Web服务的技术详细信息。
WSDL文档中的一些有用信息包括:方法名称,端口类型,服务端点,绑定,方法参数等。

UDDI

UDDI是通用描述,发现和集成的首字母缩写。
UDDI是Web服务的目录,客户端应用程序可以其中查找Web服务。
Web服务可以注册到UDDI服务器,并使它们可用于客户端应用程序。

Web服务的优势

Web服务的一些优点是:

  • 互操作性:因为Web服务通过网络工作并且使用XML技术进行通信,所以可以使用支持Web服务开发的任何编程语言来开发它。

  • 可重用性:一个Web服务可以同时被许多客户端应用程序使用。
    例如,我们可以公开用于股票技术分析的Web服务,并且所有银行和金融机构都可以使用它。

  • 松散耦合:Web服务客户端代码与服务器代码完全独立,因此我们在应用程序中实现了松散耦合。
    这导致易于维护并且易于扩展。

  • 易于部署和集成

  • 可以同时运行多个服务版本。

JAX-WS

JAX-WS代表XML Web Services的Java API。
JAX-WS是基于XML的Java API,用于构建Web服务服务器和客户端应用程序。
它是标准Java API的一部分,因此我们不需要包含其他任何可以使用它的东西。

JAX-WS示例

现在我们已经了解了Web服务的术语,让我们继续创建JAX-WS Web服务。
我们将创建一个Web服务,该服务将公开添加,删除和获取人员对象的方法。
因此,首先,我们将为数据创建一个模型bean。

Person.java

package com.theitroad.jaxws.beans;

import java.io.Serializable;

public class Person implements Serializable{

	private static final long serialVersionUID = -5577579081118070434L;
	
	private String name;
	private int age;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	
	@Override
	public String toString(){
		return id+"::"+name+"::"+age;
	}

}

现在,我们将不得不创建一个接口,在该接口中声明将在我们的JAX-WS示例Web服务中公开的方法。

PersonService.java

package com.theitroad.jaxws.service;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

import com.theitroad.jaxws.beans.Person;

@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface PersonService {

	@WebMethod
	public boolean addPerson(Person p);
	
	@WebMethod
	public boolean deletePerson(int id);
	
	@WebMethod
	public Person getPerson(int id);
	
	@WebMethod
	public Person[] getAllPersons();
}

注意,JAX-WS API使用了@WebService和@SOAPBinding注释。
我们可以采用RPC样式或者Document样式创建SOAP Web服务。
我们可以使用这些样式中的任何一种来创建Web服务,不同之处在于WSDL文件的生成方式。

现在,我们将编写实现类,如下所示。

PersonServiceImpl.java

package com.theitroad.jaxws.service;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.jws.WebService;

import com.theitroad.jaxws.beans.Person;

@WebService(endpointInterface = "com.theitroad.jaxws.service.PersonService")  
public class PersonServiceImpl implements PersonService {

	private static Map<Integer,Person> persons = new HashMap<Integer,Person>();
	
	@Override
	public boolean addPerson(Person p) {
		if(persons.get(p.getId()) != null) return false;
		persons.put(p.getId(), p);
		return true;
	}

	@Override
	public boolean deletePerson(int id) {
		if(persons.get(id) == null) return false;
		persons.remove(id);
		return true;
	}

	@Override
	public Person getPerson(int id) {
		return persons.get(id);
	}

	@Override
	public Person[] getAllPersons() {
		Set<Integer> ids = persons.keySet();
		Person[] p = new Person[ids.size()];
		int i=0;
		for(Integer id : ids){
			p[i] = persons.get(id);
			i++;
		}
		return p;
	}

}

最重要的部分是@WebService批注,其中我们将提供endpointInterface值作为Web服务的接口。
这样,当Web服务方法被调用时,JAX-WS知道要用于实现的类。

我们的网络服务业务逻辑已经准备就绪,让我们继续使用JAX-WS Endpoint类进行发布。

SOAPPublisher.java

package com.theitroad.jaxws.service;

import javax.xml.ws.Endpoint;

public class SOAPPublisher {

	public static void main(String[] args) {
		 Endpoint.publish("https://localhost:8888/ws/person", new PersonServiceImpl());  
	}

}

只需运行以上程序,您的Web服务就会在程序中的给定端点上发布。
我们可以通过在端点URL上添加?wsdl来访问其WSDL文档,如下图所示。

这是WSDL代码,我们在编写客户端代码时将使用其中的一些值。

person.wsdl

<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (https://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><!-- Generated by JAX-WS RI (https://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><definitions xmlns:wsu="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="https://www.w3.org/ns/ws-policy" xmlns:wsp1_2="https://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="https://www.w3.org/2007/05/addressing/metadata" xmlns:soap="https://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="https://service.jaxws.theitroad.local/" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns="https://schemas.xmlsoap.org/wsdl/" targetNamespace="https://service.jaxws.theitroad.local/" name="PersonServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="https://service.jaxws.theitroad.local/" schemaLocation="https://localhost:8888/ws/person?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="addPerson">
<part name="arg0" type="tns:person"></part>
</message>
<message name="addPersonResponse">
<part name="return" type="xsd:boolean"></part>
</message>
<message name="deletePerson">
<part name="arg0" type="xsd:int"></part>
</message>
<message name="deletePersonResponse">
<part name="return" type="xsd:boolean"></part>
</message>
<message name="getPerson">
<part name="arg0" type="xsd:int"></part>
</message>
<message name="getPersonResponse">
<part name="return" type="tns:person"></part>
</message>
<message name="getAllPersons"></message>
<message name="getAllPersonsResponse">
<part name="return" type="tns:personArray"></part>
</message>
<portType name="PersonService">
<operation name="addPerson">
<input wsam:Action="https://service.jaxws.theitroad.local/PersonService/addPersonRequest" message="tns:addPerson"></input>
<output wsam:Action="https://service.jaxws.theitroad.local/PersonService/addPersonResponse" message="tns:addPersonResponse"></output>
</operation>
<operation name="deletePerson">
<input wsam:Action="https://service.jaxws.theitroad.local/PersonService/deletePersonRequest" message="tns:deletePerson"></input>
<output wsam:Action="https://service.jaxws.theitroad.local/PersonService/deletePersonResponse" message="tns:deletePersonResponse"></output>
</operation>
<operation name="getPerson">
<input wsam:Action="https://service.jaxws.theitroad.local/PersonService/getPersonRequest" message="tns:getPerson"></input>
<output wsam:Action="https://service.jaxws.theitroad.local/PersonService/getPersonResponse" message="tns:getPersonResponse"></output>
</operation>
<operation name="getAllPersons">
<input wsam:Action="https://service.jaxws.theitroad.local/PersonService/getAllPersonsRequest" message="tns:getAllPersons"></input>
<output wsam:Action="https://service.jaxws.theitroad.local/PersonService/getAllPersonsResponse" message="tns:getAllPersonsResponse"></output>
</operation>
</portType>
<binding name="PersonServiceImplPortBinding" type="tns:PersonService">
<soap:binding transport="https://schemas.xmlsoap.org/soap/http" style="rpc"></soap:binding>
<operation name="addPerson">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</output>
</operation>
<operation name="deletePerson">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</output>
</operation>
<operation name="getPerson">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</output>
</operation>
<operation name="getAllPersons">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="https://service.jaxws.theitroad.local/"></soap:body>
</output>
</operation>
</binding>
<service name="PersonServiceImplService">
<port name="PersonServiceImplPort" binding="tns:PersonServiceImplPortBinding">
<soap:address location="https://localhost:8888/ws/person"></soap:address>
</port>
</service>
</definitions>

这是一个客户端程序,我们其中调用我们的JAX-WS示例Web服务。

SOAPPublisherClient.java

package com.theitroad.jaxws.service;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import com.theitroad.jaxws.beans.Person;

public class SOAPPublisherClient {

	public static void main(String[] args) throws MalformedURLException {
		URL wsdlURL = new URL("https://localhost:8888/ws/person?wsdl");
		//check above URL in browser, you should see WSDL file
		
		//creating QName using targetNamespace and name
		QName qname = new QName("https://service.jaxws.theitroad.local/", "PersonServiceImplService"); 
		
		Service service = Service.create(wsdlURL, qname);  
		
		//We need to pass interface and model beans to client
		PersonService ps = service.getPort(PersonService.class);
		
		Person p1 = new Person(); p1.setName("hyman"); p1.setId(1); p1.setAge(30);
		Person p2 = new Person(); p2.setName("Meghna"); p2.setId(2); p2.setAge(25);
		
		//add person
		System.out.println("Add Person Status="+ps.addPerson(p1));
		System.out.println("Add Person Status="+ps.addPerson(p2));
		
		//get person
		System.out.println(ps.getPerson(1));
		
		//get all persons
		System.out.println(Arrays.asList(ps.getAllPersons()));
		
		//delete person
		System.out.println("Delete Person Status="+ps.deletePerson(2));
		
		//get all persons
		System.out.println(Arrays.asList(ps.getAllPersons()));
		
	}

}

当我们执行上面的JAX-WS客户端程序时,我们得到此输出。

Add Person Status=true
Add Person Status=true
1::hyman::30
[1::hyman::30, 2::Meghna::25]
Delete Person Status=true
[1::hyman::30]

当我再次运行程序时,我们得到此输出。

Add Person Status=false
Add Person Status=true
1::hyman::30
[1::hyman::30, 2::Meghna::25]
Delete Person Status=true
[1::hyman::30]

请注意,在第二次运行中,添加人状态为false,因为它已在第一次运行中添加。

JAX-WS客户端程序

如果您看上面的程序,我们正在使用服务器代码本身。
但是,Web服务仅公开WSDL,而第三方应用程序无权访问这些类。
因此,在这种情况下,我们可以使用" wsimport"实用程序来生成客户端存根。
该实用程序随JDK的标准安装一起提供。
下图显示了运行该实用程序时得到的所有Java类。

只需将这些类复制到您的客户端项目中,唯一的变化就是我们获取PersonService实例的方式。

下面是用于此的程序,输出将与上面的客户端程序相同。
请注意,使用了" PersonServiceImplService"类,并使用了" getPersonServiceImplPort"方法来获取PersonService实例。

TestPersonService.java

package com.theitroad.jaxws.service.test;

import java.util.Arrays;

import com.theitroad.jaxws.service.Person;
import com.theitroad.jaxws.service.PersonService;
import com.theitroad.jaxws.service.PersonServiceImplService;

public class TestPersonService {

	public static void main(String[] args) {
		
		PersonServiceImplService serviceImpl = new PersonServiceImplService();
		
		PersonService service = serviceImpl.getPersonServiceImplPort();
		
		Person p1 = new Person(); p1.setName("hyman"); p1.setId(1); p1.setAge(30);
      Person p2 = new Person(); p2.setName("Meghna"); p2.setId(2); p2.setAge(25);
      
      System.out.println("Add Person Status="+service.addPerson(p1));
      System.out.println("Add Person Status="+service.addPerson(p2));
      
    //get person
      System.out.println(service.getPerson(1));
       
      //get all persons
      System.out.println(Arrays.asList(service.getAllPersons()));
       
      //delete person
      System.out.println("Delete Person Status="+service.deletePerson(2));
       
      //get all persons
      System.out.println(Arrays.asList(service.getAllPersons()));
      
	}

}