使用 Eclipse 的 Java SOAP WebServices 範例

SOAP WebServices 可以用多種方式在 Java 中開發。我們在上一個教程中學習了 JAX-WS SOAP Web Services,今天我們將學習如何使用 Eclipse 創建 SOAP Web 服務及其客戶端程序。在這裡,我們將不使用 JAX-WS,而是使用 Apache Axis,它集成在 Eclipse 中,並提供了一種快速簡便的方式將應用程序轉換為 Java Web 服務,並創建帶有測試 JSP 頁面的客戶端存根,用於測試目的。

Java 中的 SOAP Web 服務

我正在使用 Eclipse Mars Release (4.5.0) 進行本教程,但我認為這些步驟也適用於舊版本的 Eclipse。同時,請確保您已將 Apache Tomcat 或任何其他 Servlet 容器添加為 Eclipse 中的服務器。現在讓我們開始我們的 Eclipse Web 服務 實現。

SOAP Web 服務示例

開始我們在Eclipse中的SOAP Web服務示例。首先,我們將在Eclipse中創建一個簡單的Dynamic Web Project,其中包含應用程序的業務邏輯。單擊上方的“下一步”按鈕,您將進入下一頁,以提供Web項目名稱和Target Runtime。請注意,我使用的是Apache Tomcat 8,您也可以使用其他標準的Servlet容器。單擊“下一步”,您將被要求提供“上下文根”和內容目錄位置。您可以將它們保留為默認值。單擊“完成”,Eclipse將為您創建項目框架。現在,讓我們開始處理業務邏輯。對於我們的示例,我們想要發布一個Web服務,該服務可用於添加/刪除/獲取對象。因此,第一步是創建一個模型bean。

package com.journaldev.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;
	}

}

注意上面是一個簡單的Java Bean,我們實現了Serializable接口,因為我們將在網絡上傳輸它。我們還提供了toString方法的實現,當我們在客戶端打印此對象時將使用該方法。下一步是創建服務類,所以我們將有一個接口為PersonService和它的簡單實現類PersonServiceImpl。

package com.journaldev.jaxws.service;

import com.journaldev.jaxws.beans.Person;

public interface PersonService {

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

下面是實現服務類,我們使用Map來存儲Person對象作為數據源。在現實世界的編程中,我們希望將這些保存到數據庫表中。

package com.journaldev.jaxws.service;

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

import com.journaldev.jaxws.beans.Person;

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;
	}

}

這就是我們的業務邏輯,因為我們將在Web服務中使用這些,所以在這裡創建Web頁面沒有意義。請注意,上面的代碼中沒有任何關於任何種類的Web服務類的引用。

使用Eclipse在Java中進行SOAP Web服務

一旦我們的業務邏輯準備就緒,下一步是使用 Eclipse 創建一個來自此的 web 服務應用程式。創建一個新項目並選擇 Web 服務嚮導。點擊下一步按鈕,你將獲得一個頁面,該頁面需要提供 web 服務及其客戶端的詳細信息。這是創建 web 服務中最重要的頁面。確保你選擇的“Web 服務類型”為“自下而上的 Java bean Web 服務”,因為我們是採用自下而上的方法實施的。創建 web 服務有兩種方式:

  1. 契約後或自下而上方法:在這種方法中,我們首先創建實現,然後從中生成 WSDL 檔案。我們的實施適用於此類別。
  2. 契約先或自上而下方法:在這種方法中,我們首先創建 web 服務合約,即 WSDL 檔案,然後為其創建實施。

在服务实现中,提供完整分类路径的实现类PersonServiceImpl。确保在服务和客户端类型的滑块上将其移到左侧,以便生成客户端程序和用于测试我们的 Web 服务的 UI。检查 Web 服务实现中的配置,应提供服务器运行时、Web 服务运行时和服务项目的正确详细信息。通常它们会自动填充,你无需在此处进行任何更改。对于客户端配置,你可以随意提供客户端项目名称。我已将其保留为默认值SOAPExampleClient。如果单击 Web 服务运行时的链接,将会看到不同的选项,如下图所示。然而,我已将其保留为默认值。点击“下一步”按钮,然后你将能够选择要公开为 Web 服务的方法。你还可以选择 Web 服务风格,即文档或文字。你可以更改 WSDL 文档名称,但最好使用实现类名称,以避免以后混淆。点击“下一步”按钮,你将获得服务器启动页面,点击“启动服务器”按钮,然后下一个按钮将启用。点击“下一步”按钮,你将获得一个启动“Web Services Explorer”的页面。点击“启动”按钮,它将在浏览器中打开一个新窗口,你可以在其中测试 Web 服务,然后再进行客户端应用程序部分。对于我们的项目,它看起来像下面的图片。我们可以在这里进行一些基本测试,但对于我们的简单应用程序,我准备好继续创建客户端应用程序。单击 Eclipse Web Services 弹出窗口中的“下一步”按钮,你将获得客户端应用程序的源文件夹页面。点击“下一步”按钮,你将得到不同的选项,可以选择作为测试设施。我将继续使用JAX-RPC JSPs,以便客户端应用程序将生成一个我们可以使用的 JSP 页面。注意添加的getEndpoint()setEndpoint(String)方法,我们可以使用这些方法获取 Web 服务端点 URL,并在将服务器移动到其他 URL 端点时将其设置为其他 URL。点击“完成”按钮,Eclipse 将在你的工作空间中创建客户端项目,并启动客户端测试 JSP 页面,如下所示。你可以复制 URL 并在任何你喜欢的浏览器中打开。让我们测试一些我们公开的服务并查看输出。

日食SOAP Web服務測試

  • addPerson

  • getPerson

  • getAllPersons 注意到结果部分没有打印人员详情,这是因为它是自动生成的代码,我们需要稍微重构一下以获得期望的输出。在客户端项目中打开 Result.jsp,您将看到它正在使用 switch case 生成结果输出。对于 getAllPersons() 方法,在我的情况下是 case 42。请注意,在您的情况下,这可能是完全不同的。我只是按照以下所示更改了 case 42 的代码。

    case 42:
            gotMethod = true;
            com.journaldev.jaxws.beans.Person[] getAllPersons42mtemp = samplePersonServiceImplProxyid.getAllPersons();
    if(getAllPersons42mtemp == null){
    %>
    <%=getAllPersons42mtemp %>
    <%
    }else{
            String tempreturnp43 = null;
            if(getAllPersons42mtemp != null){
            java.util.List<com.journaldev.jaxws.beans.Person> listreturnp43= java.util.Arrays.asList(getAllPersons42mtemp);
            //tempreturnp43 = listreturnp43.toString();
            for(com.journaldev.jaxws.beans.Person p : listreturnp43){
            	int id = p.getId();
            	int age = p.getAge();
            	String name=p.getName();
            	%>
            	<%=id%>::<%=name %>::<%=age %>
            	<%
            	}
            }
            }      
    break;
    

    之后,我们得到以下输出,请注意 Eclipse 在这里进行热部署,所以我不需要重新部署我的应用程序。

看起來我們的Web服務和客戶端應用程序都運行正常,請確保花些時間查看Eclipse生成的客戶端存根以更深入地了解。

SOAP Web服務WSDL和配置

最後,您會注意到Web服務項目中生成了WSDL文件,如下所示。PersonServiceImpl.wsdl 代碼:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="https://service.jaxws.journaldev.com" xmlns:apachesoap="https://xml.apache.org/xml-soap" xmlns:impl="https://service.jaxws.journaldev.com" xmlns:intf="https://service.jaxws.journaldev.com" xmlns:tns1="https://beans.jaxws.journaldev.com" xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="https://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)-->
 <wsdl:types>
  <schema elementFormDefault="qualified" targetNamespace="https://service.jaxws.journaldev.com" xmlns="https://www.w3.org/2001/XMLSchema">
   <import namespace="https://beans.jaxws.journaldev.com"/>
   <element name="addPerson">
    <complexType>
     <sequence>
      <element name="p" type="tns1:Person"/>
     </sequence>
    </complexType>
   </element>
   <element name="addPersonResponse">
    <complexType>
     <sequence>
      <element name="addPersonReturn" type="xsd:boolean"/>
     </sequence>
    </complexType>
   </element>
   <element name="deletePerson">
    <complexType>
     <sequence>
      <element name="id" type="xsd:int"/>
     </sequence>
    </complexType>
   </element>
   <element name="deletePersonResponse">
    <complexType>
     <sequence>
      <element name="deletePersonReturn" type="xsd:boolean"/>
     </sequence>
    </complexType>
   </element>
   <element name="getPerson">
    <complexType>
     <sequence>
      <element name="id" type="xsd:int"/>
     </sequence>
    </complexType>
   </element>
   <element name="getPersonResponse">
    <complexType>
     <sequence>
      <element name="getPersonReturn" type="tns1:Person"/>
     </sequence>
    </complexType>
   </element>
   <element name="getAllPersons">
    <complexType/>
   </element>
   <element name="getAllPersonsResponse">
    <complexType>
     <sequence>
      <element maxOccurs="unbounded" name="getAllPersonsReturn" type="tns1:Person"/>
     </sequence>
    </complexType>
   </element>
  </schema>
  <schema elementFormDefault="qualified" targetNamespace="https://beans.jaxws.journaldev.com" xmlns="https://www.w3.org/2001/XMLSchema">
   <complexType name="Person">
    <sequence>
     <element name="age" type="xsd:int"/>
     <element name="id" type="xsd:int"/>
     <element name="name" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
  </schema>
 </wsdl:types>

   <wsdl:message name="addPersonResponse">

      <wsdl:part element="impl:addPersonResponse" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="getAllPersonsResponse">

      <wsdl:part element="impl:getAllPersonsResponse" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="deletePersonResponse">

      <wsdl:part element="impl:deletePersonResponse" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="addPersonRequest">

      <wsdl:part element="impl:addPerson" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="getPersonResponse">

      <wsdl:part element="impl:getPersonResponse" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="getPersonRequest">

      <wsdl:part element="impl:getPerson" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="deletePersonRequest">

      <wsdl:part element="impl:deletePerson" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="getAllPersonsRequest">

      <wsdl:part element="impl:getAllPersons" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:portType name="PersonServiceImpl">

      <wsdl:operation name="addPerson">

         <wsdl:input message="impl:addPersonRequest" name="addPersonRequest">

       </wsdl:input>

         <wsdl:output message="impl:addPersonResponse" name="addPersonResponse">

       </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="deletePerson">

         <wsdl:input message="impl:deletePersonRequest" name="deletePersonRequest">

       </wsdl:input>

         <wsdl:output message="impl:deletePersonResponse" name="deletePersonResponse">

       </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="getPerson">

         <wsdl:input message="impl:getPersonRequest" name="getPersonRequest">

       </wsdl:input>

         <wsdl:output message="impl:getPersonResponse" name="getPersonResponse">

       </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="getAllPersons">

         <wsdl:input message="impl:getAllPersonsRequest" name="getAllPersonsRequest">

       </wsdl:input>

         <wsdl:output message="impl:getAllPersonsResponse" name="getAllPersonsResponse">

       </wsdl:output>

      </wsdl:operation>

   </wsdl:portType>

   <wsdl:binding name="PersonServiceImplSoapBinding" type="impl:PersonServiceImpl">

      <wsdlsoap:binding style="document" transport="https://schemas.xmlsoap.org/soap/http"/>

      <wsdl:operation name="addPerson">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="addPersonRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="addPersonResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="deletePerson">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="deletePersonRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="deletePersonResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="getPerson">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="getPersonRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="getPersonResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="getAllPersons">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="getAllPersonsRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="getAllPersonsResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

   </wsdl:binding>

   <wsdl:service name="PersonServiceImplService">

      <wsdl:port binding="impl:PersonServiceImplSoapBinding" name="PersonServiceImpl">

         <wsdlsoap:address location="https://localhost:8080/SOAPExample/services/PersonServiceImpl"/>

      </wsdl:port>

   </wsdl:service>

</wsdl:definitions>

如果您在Eclipse的设计模式中打开它,它将看起来像下面的图片。 您还可以通过在Web服务端点附加?wsdl到浏览器中访问Web服务WSDL文件。 您还会注意到web.xml已被修改以使用Apache Axis作为Web服务的前端控制器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>SOAPExample</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <display-name>Apache-Axis Servlet</display-name>
    <servlet-name>AxisServlet</servlet-name>
    <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/servlet/AxisServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>*.jws</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>
  <servlet>
    <display-name>Axis Admin Servlet</display-name>
    <servlet-name>AdminServlet</servlet-name>
    <servlet-class>org.apache.axis.transport.http.AdminServlet</servlet-class>
    <load-on-startup>100</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>AdminServlet</servlet-name>
    <url-pattern>/servlet/AdminServlet</url-pattern>
  </servlet-mapping>
</web-app>

下面的图片显示了带有所有自动生成的存根和JSP页面以测试Web服务的Web服务和客户端项目。 这就是在Eclipse中使用Java示例进行SOAP Web服务的全部内容,正如您所看到的,Eclipse已自动完成所有繁重的工作,而我们的重点是为Web服务编写业务逻辑。

Source:
https://www.digitalocean.com/community/tutorials/soap-webservices-in-java-example-eclipse