应用Spring DM和CXF在TOMCAT上发布WebService
1?????? 目标
?? 动态发布
有多个Bundle需要发布WebService,所以希望创建一个Webservice Util(下面简称ws-util)的Bundle并提供易用的接口发布为OSGI的服务,其它Bundle可以通过调用该服务即可实现Webservice的发布。
?? 依赖最小化
需要发布的Bundle依赖ws-util,但不需要依赖CXF,如果把CXF替换为其他的Webservice引擎,不会引起其他Bundle的变更。
?? 编码方便
尽可能减少对业务代码的侵入。
2?????? 思路1,? 如何实现动态发布?
需要发布的Bundle依赖ws-util,调用接口即可完成发布,所以不能在ws-util中静态配置webservice。
解决的办法是利用jax-ws 中定义EndPoint接口,对该接口包装成一个类并发布为OSGI Service,其他bundle调用该service完成webservice的发布。
2,? ws-util的上下文环境是什么样的?
Project中存在WEB-INF目录,并且存在web.xml描述文件,osgi的tomcat bundle启动时会自动监视该目录并且加载该文件,并把ws-util作为war包部署到web容器中。
OSGI CORE启动时会监视METAINF.MF中的MANIFEST.MF文件,并初始化OSGI上下文,发布OSGI Service。所以ws-util处于双重的容器管理之下,一重是OSGI容器管理,一重是WEB容器管理。
Tomcat bundle也是由OSGI CORE启动,所以ws-util的OSGI上下文初始化要早于Web上下文的初始化,如果用META-INF/spring下的spring配置方式发布EndPoint包装接口,此时的CXF Bus还没有开始初始化,EndPoint找不到web server的provider,发布就不会成功。
3,? 如何把tomcat和cxf整合起来?
?
3?????? 环境配置JDK:1.6
Eclipse:3.5.2
Spring:3.0.6
CXF:2.3.1
3.1?? OSGI PlatForm的依赖BundleSRC
插件代码
Lib
CXF 依赖包
META-INF
OSGI工程的配置项
WEB-INF
当前项目要发布到Web容器中,OSGI根据该目录的Web.xml确定部署方式
4.3?? CXF依赖包lib/cxf-2.3.1.jar,
?lib/cxf-wstx-msv-validation-2.3.1.jar,
?lib/cxf-xjc-boolean-2.3.0.jar,
?lib/cxf-xjc-bug671-2.3.0.jar,
?lib/cxf-xjc-dv-2.3.0.jar,
?lib/cxf-xjc-ts-2.3.0.jar,
?lib/msv-20050913.jar,
?lib/neethi-2.0.4.jar,
?lib/oro-2.0.8.jar,
?lib/stax2-api-3.0.2.jar,
?lib/velocity-1.6.4.jar,
?lib/woodstox-core-asl-4.0.8.jar,
?lib/wsdl4j-1.6.2.jar,
?lib/xmlbeans-2.4.0.jar,
?lib/XmlSchema-1.4.7.jar,
javax.servlet,
?javax.servlet.http;version="2.5.0",
?javax.xml.ws,
?org.osgi.framework,
?org.osgi.util.tracker,
?org.springframework.beans;version="3.0.6.RELEASE",
?org.springframework.beans.factory;version="3.0.6.RELEASE",
?org.springframework.beans.factory.config;version="3.0.6.RELEASE",
?org.springframework.beans.factory.support;version="3.0.6.RELEASE",
?org.springframework.beans.factory.wiring;version="3.0.6.RELEASE",
?org.springframework.beans.factory.xml;version="3.0.6.RELEASE",
?org.springframework.context;version="3.0.6.RELEASE",
?org.springframework.context.event;version="3.0.6.RELEASE",
?org.springframework.context.support;version="3.0.6.RELEASE",
?org.springframework.core;version="3.0.6.RELEASE",
?org.springframework.core.io;version="3.0.6.RELEASE",
?org.springframework.core.io.support;version="3.0.6.RELEASE",
?org.springframework.osgi.context;version="2.0.0.M1",
?org.springframework.osgi.web.context.support;version="2.0.0.M1",
package com.boco.gutil.webservice.exports;
?
public interface WSRegister {
??? public void regiser(Object impl,String address);
public class WSRegisterImpl implements WSRegister {
??? private static final Logger logger = Logger.getLogger(WSRegisterImpl.class
?????????? .getName());
?
??? public void regiser(final Object impl, final String address) {
?????? ClassLoader clsCl = this.getClass().getClassLoader();
?????? Thread.currentThread().setContextClassLoader(clsCl);
??????
?????? logger.info(" Regiser Service @" + address);
??????
?????? Endpoint.publish(address, impl);
??? }
public class ContextStore {
??? private static BundleContext context = null;
?
??? public static BundleContext getContext() {
?????? return context;
??? }
?
??? public static void setContext(BundleContext context) {
?????? ContextStore.context = context;
??? }
public class WsActivator implements BundleActivator {
???
??? public void start(BundleContext context) throws Exception {
?????? ContextStore.setContext(context);
??????
??? }
?
???
??? public void stop(BundleContext bc) throws Exception {
?????? ContextStore.setContext(null);
??? }
?
public class CXFWrapperServlet extends CXFNonSpringServlet {
??? private static final long serialVersionUID = -6994879522066465447L;
??? private static final Logger logger = Logger.getLogger(CXFWrapperServlet.class
?????????? .getName());
???
??? public void loadBus(ServletConfig servletConfig) throws ServletException {
??????? super.loadBus(servletConfig);???????
???????
??????? Bus bus = this.getBus();
???????
??????? BusFactory.setDefaultBus(bus);
???????
??????? BundleContext context = ContextStore.getContext();
???????
??????? Dictionary<String, String> props = new? Hashtable<String, String>();
??????? props.put("context-class-loader", "service-provider");
???????
??????? context.registerService(WSRegister.class.getName(), new WSRegisterImpl(), props);
??????? logger.info("Start Deploy com.boco.gutil.webservice");
??? }
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
??? xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
??? http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
??? version="2.4">
??? <context-param>
?????? <param-name>contextConfigLocation</param-name>
?????? <param-value>
?????????? /WEB-INF/spring/*.xml
?????? </param-value>
??? </context-param>
??? <context-param>
?????? <param-name>contextClass</param-name>
??? ??? <param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
?????? </param-value>
??? </context-param>
??? <listener>
?????? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
??? </listener>
??? <servlet>
?????? <servlet-name>CXFServlet</servlet-name>
?????? <servlet-class>com.boco.gutil.webservice.context.CXFWrapperServlet</servlet-class>
?????? <load-on-startup>0</load-on-startup>
??? </servlet>
?
??? <servlet-mapping>
?????? <servlet-name>CXFServlet</servlet-name>
?????? <url-pattern>/*</url-pattern>
??? </servlet-mapping>
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Webservice
Bundle-SymbolicName: com.boco.gutil.webservice
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: BOCO
Web-ContextPath: GDPP_WS
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: com.boco.gutil.webservice.exports,
?org.apache.cxf.frontend,
?org.apache.cxf.jaxws
Bundle-ClassPath: .,
?lib/cxf-2.3.1.jar,
?lib/cxf-wstx-msv-validation-2.3.1.jar,
?lib/cxf-xjc-boolean-2.3.0.jar,
?lib/cxf-xjc-bug671-2.3.0.jar,
?lib/cxf-xjc-dv-2.3.0.jar,
?lib/cxf-xjc-ts-2.3.0.jar,
?lib/msv-20050913.jar,
?lib/neethi-2.0.4.jar,
?lib/oro-2.0.8.jar,
?lib/stax2-api-3.0.2.jar,
?lib/velocity-1.6.4.jar,
?lib/woodstox-core-asl-4.0.8.jar,
?lib/wsdl4j-1.6.2.jar,
?lib/xmlbeans-2.4.0.jar,
?lib/XmlSchema-1.4.7.jar,
?lib/xmlsec-1.4.4.jar
Import-Package: javax.servlet,
?javax.servlet.http;version="2.5.0",
?javax.xml.ws,
?org.osgi.framework,
?org.osgi.util.tracker,
?org.springframework.beans;version="3.0.6.RELEASE",
?org.springframework.beans.factory;version="3.0.6.RELEASE",
?org.springframework.beans.factory.config;version="3.0.6.RELEASE",
?org.springframework.beans.factory.support;version="3.0.6.RELEASE",
?org.springframework.beans.factory.wiring;version="3.0.6.RELEASE",
?org.springframework.beans.factory.xml;version="3.0.6.RELEASE",
?org.springframework.context;version="3.0.6.RELEASE",
?org.springframework.context.event;version="3.0.6.RELEASE",
?org.springframework.context.support;version="3.0.6.RELEASE",
?org.springframework.core;version="3.0.6.RELEASE",
?org.springframework.core.io;version="3.0.6.RELEASE",
?org.springframework.core.io.support;version="3.0.6.RELEASE",
?org.springframework.osgi.context;version="2.0.0.M1",
?org.springframework.osgi.web.context.support;version="2.0.0.M1",
?org.springframework.web.context;version="3.0.6.RELEASE"
Bundle-ActivationPolicy: lazy
Web-ContextPath: GDPP_WS
public class WSRegisterTracker extends ServiceTracker {
??? public WSRegisterTracker(BundleContext context) {
?????? super(context,WSRegister.class.getName(),null);
??? }
???
??? public Object addingService(ServiceReference reference) {
?????? Object serviceObj = context.getService(reference);
?????? //注册webservice
?????? WSRegister wsRegister = (WSRegister)serviceObj;
?????? wsRegister.regiser(new HelloWorldImpl(), "/Hello");
??????
?????? return super.addingService(reference);
??? }
public class WSClientActivator implements BundleActivator {
??? private WSRegisterTracker tracker = null;
??? public void start(BundleContext context) throws Exception {
?????? tracker = new WSRegisterTracker(context);
?????? tracker.open();
??? }
?
??? public void stop(BundleContext bundleContext) throws Exception {
?????? tracker.close();
??? }
@WebService
public interface IHelloWorld {
?
??? String sayHi(String text);
?
??? String sayHiToUser(User user);
?
@WebService
public class HelloWorldImpl implements IHelloWorld {
??? public String sayHi(String text) {
??????? System.out.println("sayHi called");
??????? return "Hello " + text;
??? }
?
??? public String sayHiToUser(User user) {
??????? System.out.println("sayHiToUser called");
??????? return "Hello "? + user.getName();
??? }
public class User implements Serializable{
??? String name;
?
??? public User() {
??? }
??? public User(String s) {
??????? name = s;
??? }
?
??? public String getName() {
??????? return name;
??? }
?
??? public void setName(String s) {
??????? name = s;
??? }
}
?