设为首页 收藏本站
查看: 511|回复: 0

[经验分享] 应用Spring DM和CXF在TOMCAT上发布WebService

[复制链接]

尚未签到

发表于 2017-2-6 11:43:55 | 显示全部楼层 |阅读模式
1       目标
项目应用Spring DM实现模块化开发。系统和其他进程之间的控制信息希望能通过Webservice实现。要求如下:
Ø  动态发布
有多个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整合起来?
       1)注册Activator, 在activator初始化方法中获取osgi上下文。
    2)web上下文加载CxfNoSpringServlet时,初始化cxf bus后,获取缓存中的osgi上下文,并且把EndPoint包装类注册为osgi 服务。
 
3       环境配置
JDK:1.6
Eclipse:3.5.2
Spring:3.0.6
CXF:2.3.1
3.1   OSGI PlatForm的依赖Bundle
Spring 相关Bundle
org.springframework.beans-3.0.6.RELEASE.jar
org.springframework.context.support-3.0.6.RELEASE.jar
 org.springframework.web-3.0.6.RELEASE.jar
 org.springframework.context-3.0.6.RELEASE.jar
 org.springframework.asm-3.0.6.RELEASE.jar
 org.springframework.expression-3.0.6.RELEASE.jar
 org.springframework.web.servlet-3.0.6.RELEASE.jar
 org.springframework.core-3.0.6.RELEASE.jar
 org.springframework.aspects-3.0.6.RELEASE.jar
 org.springframework.aop-3.0.6.RELEASE.jar
 org.springframework.oxm-3.0.6.RELEASE.jar
Spring DM 相关Bundle
org.eclipse.osgi.services_3.2.0.v20090520-1800.jar
 spring-osgi-core-2.0.0.M1.jar
 spring-osgi-extender-2.0.0.M1.jar
 spring-osgi-annotation-2.0.0.M1.jar
 spring-osgi-web-extender-2.0.0.M1.jar
 spring-osgi-io-2.0.0.M1.jar
 spring-osgi-web-2.0.0.M1.jar
XML 相关Bundle
com.springsource.org.apache.xml.serializer-2.7.1.jar
 com.springsource.javax.xml.ws-2.1.1.jar
 com.springsource.javax.xml.stream-1.0.1.jar
 com.springsource.javax.xml.bind-2.2.0.jar
 com.springsource.org.apache.xmlcommons-1.3.4.jar
 com.springsource.javax.xml.soap-1.3.0.jar
 com.springsource.org.apache.xml.resolver-1.2.0.jar
 com.springsource.org.dom4j-1.6.1.jar
 com.springsource.org.apache.xerces-2.9.1.jar
其他依赖包
com.springsource.net.sf.cglib-2.2.0.jar
 com.springsource.javax.activation-1.1.1.jar
 javax.el-2.2.0.v201105051105.jar
 com.springsource.org.apache.commons.el-1.0.0.jar
 com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
Tomcat启动包
catalina.start.osgi-1.0.0.jar
 catalina.osgi-5.5.23-SNAPSHOT.jar
      
所有这些Bundle可以在http://ebr.springsource.com/repository/app/ 网站下载。
4       创建Webservice Bundle
4.1   创建Plug-in project

4.2   Project 目录结构

 
目录说明如下:
 
SRC
插件代码
Lib
CXF 依赖包
META-INF
OSGI工程的配置项
WEB-INF
当前项目要发布到Web容器中,OSGI根据该目录的Web.xml确定部署方式
4.3   CXF依赖包
Webservice lib下面的jar都是来自于cxf,但是我们用不了所有的jar包,需要根据我们的需要剔除一部分。
我们需要把webservice发布到Tomcat中,并且以jax-ws的方式,可以从cxf的lib中剔除jetty和restful实现相关的jar包。
另外我们的OSGI platform中已经有web相关的bundle,所以servlet相关的jar也要剔除。
剩下的jar列表如下:
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
4.4   MANIFEST.MF添加需要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"
 
导入结束后,会在project的plug-in Dependencies下出现下列bundle:

 
4.5   JAVA 源码说明
4.5.1   类结构

说明:
WSRegister
EndPoint包装类接口
WSRegisterImpl
包装接口实现类
CXFWrapperServlet
CXFNoSpringServlet
WsActivator
OSGI启动类
ContextStore
OSGI 上下文缓存
 
4.5.2   WSRegister
package com.boco.gutil.webservice.exports;

 

public interface WSRegister {

    public void regiser(Object impl,String address);

}
 
4.5.3   WSRegisterImpl
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);

    }

}
4.5.4   ContextStore
public class ContextStore {

    private static BundleContext context = null;

 

    public static BundleContext getContext() {

       return context;

    }

 

    public static void setContext(BundleContext context) {

       ContextStore.context = context;

    }

}
 
4.5.5   WsActivator
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);

    }

 

}
4.5.6   CXFWrapperServlet
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");

    }

}
4.5.7   Web.xml
<?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>

</web-app>
4.5.8   MANIFEST.MF
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

Bundle-Activator: com.boco.gutil.webservice.context.WsActivator
其中:
Web-ContextPath: GDPP_WS

设置webservice的web 上下文路径。
Bundle-Activator: com.boco.gutil.webservice.context.WsActivator
设置ws-util osgi启动时触发器。
5       发布WebService(依赖ws-util的bundle)
5.1   创建ServiceTracker
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);

    }

}
 
5.2   创建Activator
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();

    }

}
5.3   接口,实现类和引用类
@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;

    }

}
 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-338322-1-1.html 上篇帖子: Coder 爱翻译 How Tomcat Works 第四章 第一部分 下篇帖子: webSphere和TomCat的区别以及乱码问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表