14.6 整合与Spring开发Web Service
CXF框架另一个具有吸引力的地方就是CXF框架能与Spring框架有机地整合到一起,借助于Spring IoC容器的帮助,使用CXF开发Web Service将会更加简单。
14.6.1 在Spring中使用CXF
CXF和Spring可以无缝地整合在一起,实际上使用Spring来发布Web Service将更加简单,下面的程序将示范使用Spring来发布前面的Web Service服务类。
提示
为了在CXF应用中使用Spring框架,我们还应将Spring框架的核心JAR包、编译和运行所依赖的第三方类库添加到Web应用的WEB-INF\lib路径下。CXF 2.4.0支持Spring 3.0.x系列,本示例程序整合的是Spring 3.0.5。关于Spring用法的介绍,读者可以参阅疯狂Java体系的《轻量级Java EE企业应用实战》一书。
本应用将改为使用Tomcat作为Web服务器,在一个Web应用中发布Web Service。下面先修改本应用的web.xml文件,让该Web应用加载CXF的核心Servlet,并自动加载Spring容器:
程序清单:codes\14\14.6\cxf-spring\WEB-INF\web.xml
上面的web.xml文件指定了应用启动时将自动加载applicationContext.xml文件,并根据该文件创建Spring容器。除此之外,还配置了CXF的核心Servlet——CXFServlet,并指定该Servlet拦截来自yeeku-services/*的所有请求。
一旦加载了Spring容器,CXF就将改为使用Spring来发布Web Service,而不再需要程序员自己定义服务器类来发布Web Service。
CXF为Spring新增了大量XML文档,专门用于扩展Spring功能,这些XML位于cxf-2.4.0.jar的META-INF\cxf路径下,如图14.14所示。
图14.14 cxf-2.4.0.jar文件中包含的XML配置文件
本示例应用需要在Spring配置文件中导入如下两个XML文档:
META-INF/cxf/cxf.xml。
META-INF/cxf/cxf-servlet.xml。
在Spring配置文件中导入以上所示的两个XML 文档之后,还需要向Spring配置文件中导入一个命名空间为http://cxf.apache.org/jaxws的XML Schema,这份XML Schema也由CXF提供。
接下来就可以在Spring配置文件中通过<endpoint…/>元素来发布Web Service了。<endpoint…/>元素位于http://cxf.apache.org/jaxws命名空间之下,使用<endpoint.../>元素时可指定以下几个属性:
id:指定所定义的Bean在Spring容器中的唯一标识。
implementor:指定Web Service的实现类,或者引用容器中另一个已有的Bean实例。
address:指定所创建的Web Service的地址,因为CXF不知道该Web应用对应的URL,也不知道Web服务器的监听端口,因此address属性指定的只是一个相对地址,CXF将会在运行时动态确定该Web Service的服务地址。
下面是本示例应用中的Spring的配置文件:
程序清单:codes\14\14.6\cxf-spring\WEB-INF\applicationContext.xml
使用<endpoint…/>元素发布Web Service时,implementor属性既可指定Web Service服务实现类,也可指定容器中另一个已有的Bean实例。implementor属性为容器中其他Bean的配置示例如下:
完成上面的Web应用之后,将该Web应用部署到Tomcat服务器中,然后启动Tomcat服务器,笔者的Tomcat在端口8888监听,在浏览器地址栏里输入http://localhost:8888/cxf-spring/yeeku-services/ crazyit?wsdl即可看到如图14.15所示WSDL文档。
图14.15 使用CXF+Spring发布Web Service
由于CXF和Spring的无缝整合,因此可以非常方便地利用Spring容器来发布Web Service,然后再利用Spring提供的IoC功能,这样我们就可以非常方便地将Spring容器里的业务逻辑组件注入Web Service服务类中,从而将Spring容器中的业务逻辑组件暴露成Web Service,允许远程调用。关于如何使用CXF来重构原有的系统,将原有系统的业务逻辑方法暴露成Web Service,将在最后一章的综合案例中给出示范。
14.6.2 通过Spring启用CXF拦截器
前面介绍了整合Spring与CXF开发Web Service的方法,借助于Spring IoC容器的支持,利用CXF开发Web Service非常便捷,只要在Spring容器中配置、发布Web Service即可。但需要指出的是,由于这种配置方式不需要开发者编写任何代码,因此不能通过前面介绍的方式来添加拦截器。
当用Spring整合CXF来开发Web Service时,拦截器也是通过配置文件来进行添加的,此时可通过在<jaxws:endpoint…/>元素中添加以下两个子元素来启用拦截器:
<jaxws:inInterceptors…/>:添加In拦截器。
<jaxws:outInterceptors…/>:添加Out拦截器。
<jaxws:inInterceptors…/>、<jaxws:outInterceptors…/>两个元素在功能上基本相似:一个用于配置In拦截器,一个用于配置Out拦截器。它们的用法几乎相同,它们都可以接受以下两个子元素来添加拦截器:
<bean…/>:配置一个嵌套Bean作为拦截器。
<ref…/>:引用容器中一个已有的Bean作为拦截器。
下面示例示范了如何在应用程序的业务逻辑组件上包装一层Web Service,Web Service组件需要依赖于业务逻辑组件来提供服务。本示例的Web Service组件接口如下:
程序清单:codes\14\14.6\auth-cxf-spring\WEB-INF\src\org\crazyit\cxfapp\ws\UserServiceWs.java
这个Web Service接口看不出任何特殊之处,它只是定义了Web Service应该暴露的3个操作(方法),接下来的Web Service实现类则需要依赖于业务逻辑组件,并通过调用业务逻辑组件的方法来实现Web Service操作。下面是Web Service组件的实现类:
程序清单:codes\14\14.6\auth-cxf-spring\WEB-INF\src\org\crazyit\cxfapp\ws\impl\UserServiceWsImpl.java
正如从该Web Service组件的实现类中粗体字代码所看到的,该Web Service组件每个方法的实现都是通过调用UserService组件的方法来实现的——也就是说,Web Service只是在业务逻辑组件上包装的一层,这就可以将系统已有的业务功能暴露成Web Service操作了。
提供了上面业务Web Service的接口和实现类之后,接下来还要在Spring容器中配置该Web Service组件,用<jaxws:endpoint…/>元素把它暴露成Web Service即可。Spring配置文件如下:
程序清单:codes\14\14.6\auth-cxf-spring\WEB-INF\applicationContext.xml
上面配置文件中,粗体字代码首先把UserServiceWsImpl配置成一个普通Bean:usWs,接下来配置文件使用<jaxws…/>元素把这个普通Bean暴露成Web Service——此时使用<jaxws:endpoint…/>元素时指定implementor="#usWs",这就表明把容器中已有的usWs暴露成Web Service组件。
<jaxws:endpoint…/>元素里包含的粗体字代码用于添加拦截器,通过这种方式添加拦截器的结果与前面在代码中添加拦截器的结果完全一样。
14.6.3 在Spring容器中配置Web Service客户端
很多时候,开发者开发的应用程序需要依赖远程Web Service服务,这就需要在应用程序中调用远程Web Service组件,如果采用显式调用的方式显然太不优雅了。Spring与CXF整合之后,则可以把远程Web Service配置成Spring容器中的Bean,这个Bean既可被注入其他Bean实例中,又可通过Spring容器来显式地获取、调用。
为了在Spring容器中配置Web Service客户端,可借助于<jaxws:client…/>元素,该元素可指定如下几个常用属性:
● id:该Bean的唯一标识。
● address:指定远程Web Service的服务地址。
● serviceClass:指定远程Web Service所实现的接口的全限定类名。
● serviceName:被调用的Web Service的名称。
● endpointName:被调用的Endpoint的名字。
除此之外,<jaxws:client…/>元素内部同样也可使用<jaxws:inInterceptors…/>、<jaxws:outInterceptors…/>两个子元素来添加拦截器。
下面Spring配置文件中配置了一个Web Service客户端,该客户端可以作为远程Web Service的代理,它既可以被注入其他Bean实例中,也可以通过Spring容器来显式地获取、调用。下面是配置文件的详细代码:
程序清单:codes\14\14.6\auth-cxf-spring-client\WEB-INF\applicationContext.xml
通过上面粗体字代码在Spring容器中配置了Web Service客户端之后,该配置片段所配置的usWsClient将可作为远程Web Service的代理,应用程序即可直接获取usWsClient Bean、并调用它所包含的方法(实际上将会变成调用远程Web Service),也可将usWsClient Bean注入容器里的其他Bean中,其他Bean即可通过它来调用远程Web Service。