当前位置: 代码迷 >> Web前端 >> 简略的Jax-WS WebService实现
  详细解决方案

简略的Jax-WS WebService实现

热度:474   发布时间:2013-12-10 15:05:55.0
简单的Jax-WS WebService实现

目录

?

1???? 定义Service

2???? 服务端发布Service

3???? 客户端访问Service

4???? 基于SpringJax-ws WebService

4.1???? Service定义

4.2???? 服务端发布Service

4.3???? 客户端获取Service

?

?????? Jax-wsWebService的一种规范。

1?????? 定义Service

?????? Jax-wsWebService定义是通过注解进行的,我们必须在其WebService类的接口上使用@WebService注解进行标记。

?

@WebService
public interface HelloWorld {
 
   public String sayHi(String who);
   
}

????????

如上,我们把HelloWorld定义为一个WebService,其对应有一个sayHi操作。其对应的实现类如下:?

?

public class HelloWorldImpl implements HelloWorld {
 
   @Override
   public String sayHi(String who) {
      return "Hi, " + who;
   }
 
}

2?????? 服务端发布Service

?????? 对于Jax-ws WebService而言,发布Service有两种方式。

第一种:

?

public class Server {
 
   private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
   
   public static void main(String args[]) {
      HelloWorld hw = new HelloWorldImpl();
      Endpoint.publish(ADDRESS, hw);
   }
   
}

?

第二种:?

?

public class Server {

	private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
	
	public static void main(String args[]) {
		HelloWorld hw = new HelloWorldImpl();
		JaxWsServerFactoryBean jwsFactory = new JaxWsServerFactoryBean();
		jwsFactory.setAddress(ADDRESS);	//指定WebService的发布地址
		jwsFactory.setServiceClass(HelloWorld.class);//WebService对应的类型
		jwsFactory.setServiceBean(hw);//WebService对应的实现对象
		jwsFactory.create();
	}
	
}

?

?????? 发布之后我们就可以通过发布地址?wsdl查看WebService的定义了(WSDLWebService Document Location的简称,即WebService文档位置的意思)。通过在浏览器输入http://localhost:8080/test/jaxws/services/HelloWorld?wsdl我们可以看到如下内容:

?

This XML file does not appear to have any style information associated
with it. The document tree is shown below.
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://jaxws.sample.cxftest.tiantian.com/"
	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
	name="HelloWorldImplService" targetNamespace="http://jaxws.sample.cxftest.tiantian.com/">
	<wsdl:types>
		<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
			xmlns:tns="http://jaxws.sample.cxftest.tiantian.com/"
			elementFormDefault="unqualified" targetNamespace="http://jaxws.sample.cxftest.tiantian.com/"
			version="1.0">
			<xs:element name="sayHi" type="tns:sayHi" />
			<xs:element name="sayHiResponse" type="tns:sayHiResponse" />
			<xs:complexType name="sayHi">
				<xs:sequence>
					<xs:element minOccurs="0" name="arg0" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="sayHiResponse">
				<xs:sequence>
					<xs:element minOccurs="0" name="return" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
		</xs:schema>
	</wsdl:types>
	<wsdl:message name="sayHiResponse">
		<wsdl:part element="tns:sayHiResponse" name="parameters"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="sayHi">
		<wsdl:part element="tns:sayHi" name="parameters"></wsdl:part>
	</wsdl:message>
	<wsdl:portType name="HelloWorld">
		<wsdl:operation name="sayHi">
			<wsdl:input message="tns:sayHi" name="sayHi"></wsdl:input>
			<wsdl:output message="tns:sayHiResponse" name="sayHiResponse"></wsdl:output>
		</wsdl:operation>
	</wsdl:portType>
	<wsdl:binding name="HelloWorldImplServiceSoapBinding"
		type="tns:HelloWorld">
		<soap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="sayHi">
			<soap:operation soapAction="" style="document" />
			<wsdl:input name="sayHi">
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output name="sayHiResponse">
				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="HelloWorldImplService">
		<wsdl:port binding="tns:HelloWorldImplServiceSoapBinding"
			name="HelloWorldImplPort">
			<soap:address location="http://localhost:8080/test/jaxws/services/HelloWorld" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>

???

?????? 我们可以看到在上面我们的sayHi操作的参数who变成了arg0,这是因为接口在被编译为class文件的时候不能保存参数名,有时候这会影响可读性。如果需要参数名显示的可读性强一些的话,我们可以使用@WebParam来指定,如:

?

@WebService(serviceName="!@#$%^", name="123456")
public interface HelloWorld {
 
   public String sayHi(@WebParam(name="who") String who);
   
}

?

@WebServiceserviceName可以用来指定service的名称,默认情况下如果Service是通过Endpoint.publish()方法发布的则serviceName为实现类的简单名称+Service(如HelloWorldImplService),如果是通过JaxWsServerFactoryBeancreate方法发布的则为接口的简单名称+Service(如HelloWorldService)。name属性可以用来指定service对应的portName,默认情况下如果Service是通过Endpoint.publish()方法发布的则portName为实现类的简单名称+Port(如HelloWorldImplPort),如果是通过JaxWsServerFactoryBeancreate方法发布的则为接口的简单名称+Port(如HelloWorldPort)。?

3?????? 客户端访问Service

类似于WebService简单实现里面的ClientProxyFactoryBean,在使用Jax-ws时我们可以通过JaxWsProxyFactoryBean来访问服务,如:

?

public class Client {

	private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
	
	public static void main(String args[]) {
		JaxWsProxyFactoryBean jwpFactory = new JaxWsProxyFactoryBean();
		jwpFactory.setAddress(ADDRESS);
		jwpFactory.setServiceClass(HelloWorld.class);
		HelloWorld hw = (HelloWorld)jwpFactory.create();
		String response = hw.sayHi("world");
		System.out.println(response);
	}
	
}

?

除了上面的方式之外,我们还可以这样获取Service

?

	//第一个参数为服务发布的targetNameSpace,可以通过查看对应的wsdl文件获得,默认是发布Service所在包的包名倒过来的形式;第二个参数是serviceName
	private final static QName SERVICE_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldService");
	//第一个参数是服务发布的targetNameSpace,第二个参数是portName
	private final static QName PORT_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldPort");
	//服务发布的地址
	private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
	
	public static void main(String args[]) {
		Service service = Service.create(SERVICE_NAME);
		//根据portName、服务发布地址、数据绑定类型创建一个Port。
		service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, ADDRESS);//默认是SOAP1.1Binding
		//获取服务
		HelloWorld hw = service.getPort(HelloWorld.class);
		String response = hw.sayHi("world");
		System.out.println(response);
	}
	??

?

?????? 在上面的代码中我们只需要有一个Service实例,就能通过它来获取真正的WebService,所以,我们如果把上面的代码改成如下形式也是可以的。?

?

	//第一个参数为服务发布的targetNameSpace,可以通过查看对应的wsdl文件获得,默认是发布Service所在包的包名倒过来的形式;第二个参数是serviceName
	private final static QName SERVICE_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldService");
	//第一个参数是服务发布的targetNameSpace,第二个参数是portName
	private final static QName PORT_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldPort");
	//服务发布的地址
	private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
	
	public static void main(String args[]) {
		Service service = Service.create(null);
		//根据portName、服务发布地址、数据绑定类型创建一个Port。
		service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, ADDRESS);//默认是SOAP1.1Binding
		//获取服务
		HelloWorld hw = service.getPort(HelloWorld.class);
		String response = hw.sayHi("world");
		System.out.println(response);
	}

?

???????

上面这种通过Service来获取WebService的方法是不适用前面介绍的简单WebService实现的,即不适用获取通过ServerFactoryBean发布的WebService

?

4?????? 基于SpringJax-ws WebService

4.1???? Service定义?

?????? Service定义跟之前的定义是一样的。?

4.2???? 服务端发布Service

?????? 首先在web.xml文件中定义一个CXFServlet,用于发布和拦截WebService请求。

?

	<!-- Jax-ws实现 -->
	<servlet>
		<display-name>jaxws-cxf</display-name>
		<servlet-name>jaxws-cxf</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
		<init-param>
			<param-name>config-location</param-name>
			<param-value>WEB-INF/jaxws-cxf-servlet.xml</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>jaxws-cxf</servlet-name>
		<url-pattern>/jaxws/services/*</url-pattern>
	</servlet-mapping>

??

?????? 接下来在我们的WebService配置文件里面定义我们的WebService发布,即CXFServlet指定的jaxws-cxf-servlet.xml文件(默认是cxf-servlet.xml文件)。这里我们定义如下:

?

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<!-- 相当于使用Endpoint.publish()进行服务发布 -->
	<jaxws:endpoint address="/HelloWorld" implementorClass="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>

	<!-- 相当于使用JaxWsServerFactoryBean进行服务发布 -->
	<jaxws:server address="/HelloWorld2" serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
	
	<!-- JaxWsServerFactoryBean使用外部bean作为服务进行发布 -->
	<jaxws:server address="/HelloWorld3" serviceBean="#hw"/>
	<!-- 普通bean对象 -->
	<bean id="hw" class="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
	
	<!-- JaxWsServerFactoryBean使用内部bean作为服务进行发布 -->
	<jaxws:server address="/HelloWorld4">
		<jaxws:serviceBean>
			<bean class="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
		</jaxws:serviceBean>
	</jaxws:server>

</beans>

4.3???? 客户端获取Service

?????? 客户端可以直接从Springbean配置文件中把WebService配置为一个个普通的Spring bean对象进行使用。只是在定义之前需要往bean配置文件中引入Jax-ws的命名空间。这里我们在classpath下定义一个jaxws-cxf-client.xml文件,其内容如下所示:

?

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<jaxws:client id="hw"
		address="http://localhost:8080/test/jaxws/services/HelloWorld"
		serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld" />

	<jaxws:client id="hw2"
		address="http://localhost:8080/test/jaxws/services/HelloWorld2"
		serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>
		
	<jaxws:client id="hw3"
		address="http://localhost:8080/test/jaxws/services/HelloWorld3"
		serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>
		
	<jaxws:client id="hw4"
		address="http://localhost:8080/test/jaxws/services/HelloWorld4"
		serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>

</beans>

?

?????? 之后我们就可以把这些定义好的WebService当做一个普通的bean对象来使用了,如:

?

public class SpringClient {

	public static void main(String args[]) {
		ApplicationContext context = new ClassPathXmlApplicationContext("jaxws-cxf-client.xml");
		accessService(context, "hw");
		accessService(context, "hw2");
		accessService(context, "hw3");
		accessService(context, "hw4");
	}
	
	private static void accessService(ApplicationContext context, String beanName) {
		HelloWorld hw = context.getBean(beanName, HelloWorld.class);
		System.out.println(hw.sayHi("world"));
	}
	
}

?

??

?

?

  相关解决方案