使用 Eclipse 的 Java 示例中的 SOAP Web 服务
Java 中的 Soap Webservices 可以通过多种方式开发。我们在上一篇教程中学习了JAX-WS SOAP Web 服务,今天我们将学习如何使用 Eclipse 创建 SOAP Web 服务及其客户端程序。在这里我们将不使用 JAX-WS,我们将使用集成在 Eclipse 中的Apache Axis,并提供快速简便的方法将应用程序转换为 Java Web 服务,并使用测试 JSP 页面创建客户端存根以用于测试目的。
Java 中的 SOAP Web 服务
我在本教程中使用Eclipse Mars Release (4.5.0),但我认为这些步骤也适用于旧版本的 eclipse。另外,请确保已在 Eclipse 中添加 Apache Tomcat 或任何其他 servlet 容器作为服务器。现在让我们开始实现Eclipse Web 服务。
SOAP Web 服务示例
让我们开始使用 Eclipse 中的 SOAP Web 服务示例。首先,我们将在 Eclipse 中创建一个简单的动态 Web 项目,它将包含我们应用程序的业务逻辑。单击上面的下一步按钮,您将进入下一页以提供您的 Web 项目名称和目标运行时。请注意,我使用的是 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 服务类。
使用 Eclipse 的 Java SOAP Web 服务
Once our business logic is ready, next step is to use Eclipse to create a web service application from this. Create a new project and select Web Service wizard. Click Next button and you will get a page where web service and it’s client details have to be provided. This is the most important page in creating web service. Make sure you select “Web Service type” as “Bottom up Java bean Web Service” because we are implementing with bottom up approach. There are two ways to create web service:
- Contract last or Bottom up approach: In this approach we first create the implementation and then generate the WSDL file from it. Our implementation fits in this category.
- Contract first or Top Down Approach: In this approach, we first create the web service contract i.e. WSDL file and then create the implementation for it.
In the service implementation, provide the implementation class PersonServiceImpl
fully classified path. Make sure you move the slider in service and client type to left side so that it can generate client program and also UI to test our web service. Check for the configurations in web service implementation, you should provide correct details for Server runtime, Web service runtime and service project. Usually they are auto populated and you don’t need to make any changes here. For client configurations, you can provide the client project name as you like. I have left it to default as SOAPExampleClient
. If you will click on the link for web service runtime, you will get different options as shown in below image. However I have left it as the default one. Click on Next button and then you will be able to choose the methods that you want to expose as web service. You will also be able to choose the web service style as either document or literal. You can change the WSDL document name but it’s good to have it with implementation class name to avoid confusion later on. Click on Next button and you will get server startup page, click on the “Start server” button and then next button will enable. Click on Next button and you will get a page to launch the “Web Services Explorer”. Click on Launch button and it will open a new window in the browser where you can test your web service before moving ahead with the client application part. It looks like below image for our project. We can do some sanity testing here, but for our simple application I am ready to go ahead with client application creation. Click on the Next button in the Eclipse web services popup window and you will get a page for source folder for client application. Click on Next button and you will get different options to choose as test facility. I am going ahead with JAX-RPC JSPs so that client application will generate a JSP page that we can use. Notice the methods getEndpoint()
and setEndpoint(String)
added that we can use to get the web service endpoint URL and we can set it to some other URL in case we move our server to some other URL endpoint. Click on Finish button and Eclipse will create the client project in your workspace, it will also launch client test JSP page as shown below. You can copy the URL and open in any browser you would like. Let’s test some of the services that we have exposed and see the output.
Eclipse SOAP Web Service Test
-
addPerson
-
getPerson
-
getAllPersons 请注意,结果部分未打印 Person 详细信息,这是因为它是自动生成的代码,我们需要对其进行一些重构才能获得所需的输出。在客户端项目中打开 Result.jsp,您将看到它使用 switch case 来生成结果输出。对于 getAllPersons() 方法,在我的情况下是案例 42。请注意,在您的案例中可能完全不同。我只是更改了案例 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 中以设计模式打开它,它将如下图所示。您还可以通过将?wsdl附加到 Web 服务端点来通过浏览器访问 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>
下图显示了 Web 服务和客户端项目,其中包含所有自动生成的存根和 JSP 页面,用于测试 Web 服务。这就是使用 Eclipse 的 Java 示例中的 soap webservices,正如您所见,所有困难的部分都由 Eclipse 自动完成,我们所有的重点是为我们的 Web 服务编写业务逻辑。