WebService是一种跨编程语言、跨操作系统平台的远程调用技术,广泛应用在实际开发,接口实现,系统集成。
服务端
- List item
添加maven依赖
项目中除了spring相关的依赖以外,还需添加下面两个依赖。
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.3.5</version>
<scope>compile</scope>
</dependency>
- 配置web.xml
除了常规的spring相关配置,这里需要添加cxfServlet的配置。
<!-- 1.cxfServlet配置-->
<servlet>
<servlet-name>cXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cXFServlet</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>
<!-- 2.配置spring容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
<!-- 3.监听器-->
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- 编写webService接口以及实现类
IHelloService 接口类
接口需要标注@webservice注解
@WebService
public interface IHelloService {
/**
* 对外发布服务接口的方法
* @param name
*/
public String welcome(String name);
}
HelloServiceImpl 接口实现类
public class HelloServiceImpl implements IHelloService {
@Override
public String welcome(String name) {
return "welcome to webService "+name;
}
}
- 配置applicationContext.xml
在命名空间中需要添加cxf相关的xsd,然后配置服务对应的信息,包括服务地址,服务类等
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<cxf:server address="/hello">
<jaxws:serviceBean>
<bean class="service.impl.HelloServiceImpl"></bean>
</jaxws:serviceBean>
</cxf:server>
</beans>
-
启动web服务,测试
服务启动成功后,我们可以在浏览器中访问:http://localhost:8081/webservice/hello?wsdl
其中,http://localhost:8081
为我们服务器访问入口,/webservice
为我们在web.xml
配置文件中配置的cxfServlet
对应的servlet-mapping
,/hello
为该服务访问的address
地址,最后还需要加上?wsdl
访问wsdl说明书。
下图为ie浏览器的显示效果,我测试的火狐浏览器则显示空白,对应f12的内容与下图内容一致。
客户端 -
添加cxf相关依赖
-
导入服务接口类型对应的类
这里,我们需要将服务端的IHelloService和HelloServiceImpl添加到客户端代码中。另外,不管是客户端还是服务端,IHelloService接口都是需要标注@webService注解的。 -
编写客户端的applicationContext.xml
服务端定义了接口服务类型,服务地址,与之对应地,客户端同样需要配置服务地址,服务接口类型。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd"
<jaxws:client id="helloService" serviceClass="service.impl.HelloServiceImpl" address="http://localhost:8081/webservice/hello"></jaxws:client>
</beans>
- 编写单元测试
这里使用到了spring的单元测试,所以,不光要导入junit
的依赖,还需要spring-test
的依赖。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Client {
//注入对象
@Resource
private HelloServiceImpl helloService;
@Test
public void doClientRemote(){
System.out.println(helloService);
String content = helloService.welcome("Elaine");
System.out.println(content);
}
}
- 查看输出结果
org.apache.cxf.jaxws.JaxWsClientProxy@45905bff
welcome to webService Elaine
可以发现,我们获取的HelloServiceImpl 对象是代理对象,因为事先了相关接口,自然是通过jdk动态代理实现的。
查看服务端输出时,有这样一个警告
org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://impl.service/}welcome found. Expected {http://service/}welcome.
很好理解,我们在单元测试获取的代理对象类型为实现类,cxf更希望我们直接用接口类型。替换为:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Client {
//注入对象
@Resource
private IHelloService helloService;
@Test
public void doClientRemote(){
System.out.println(helloService);
String content = helloService.welcome("Elaine");
System.out.println(content);
}
}
重新测试,无警告,无报错。