• WebService-CXF 学习笔记


    什么是CXF

    Apache CXF = Celtix + Xfire
    支持多种协议:
    SOAP1.1,1.2
    XML/HTTP
    CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)

    并可以与Spring进行快速无缝的整合
    灵活的部署:可以运行在Tomcat,Jboss,Jetty(内置),IBMWS,BeaWL上面。

     

    下载:

     CXF的结构:

     

    下载完成后将其解压到某个目录下:

      

     安装CXF的其他支持项目

    Ant
    Tomcat
    并设置以下环境变量:

    JAVA_HOME 
    CXF_HOME
    ANT_HOME
    CATALINA_HOME
    Path = %JAVA_HOME%in;%CXF_HOME%in;%CATALINA_HOME%in;%ANT_HOME%in
    CLASSPATH=.;%CXF_HOME%libcxf-manifest.jar;.uildclasses
    View Code

     用ANT来构造第一个CXF示例:

    在cxf_homesamplesjava_first_pojo目录下启动服务器:
    在命令行模式下进入上述目录:
    执行 以下命令 ant server
    在同一目录下打开新命令行窗口运行:
    ant client

    查看它的源代码并修改运行:

    用ANT将它发布到Tomcat服务器上: 

    1、执行ant clean清除以前生成的代码
    2、执行ant war打包此应用。
    3、执行ant deploy –Dtomcat=true将项目发布到tomcat的服务器上。
    4、启动tomcat服务器
    5、打开IE的地址栏输入:
    http://localhost:9999/helloworld/services/hello_world?wsdl
    或:http://localhost:9999/helloworld/services
    6、在命令行执行:
    ant client-servlet –Dbase.url=http://localhost:9999
    或在MyEclipse的WebServiceExplorer中访问这个WebService
    7、停止tomcat服务器。
    8、卸载应用:ant undeploy –Dtomcat=true
    9、清空项目:ant clean

     在Eclipse中开发CXF的JavaSE应用:

     导入CXF中的 所有jar文件。可以通过WACH_JARS来观察各jar文件的用途。

    建立好之后的项目如
    图所示:

    CXF发布服务的类:

    用两个不同的类发布应用:
    ServerFactoryBean -- FacotryBean
    JaxWsServerFactoryBean(建议使用此类)

     服务与客户端类调用原则:

     

    使用ServerFactoryBean发布服务:

    使用ServerFactoryBean发布服务。
    使用CXF发布一个服务,与JDK6发布一个服务完全不同
    * 即使是不使用@WebService注解,一样可以发布成功
    * 即使此类没有对外公布的方法一样可以发布成功

    使用ClientProxyFactoryBean客户端调用:

    使用ServerFactoryBean发布服务以后,在没有接口的情况下,可以使用wsimport生成的客户端代码调用成功。
    但如果要使用ClientProxyFactoryBean客户端去调用服务器,则必须要先在服务器端创建一个接口。(一直以来,Spring都要求面向接口编程,而cxf与Spring能很好的整合,也就在此。),所以,必须要重写服务器端的代码。这将导致刚才使用wsimport生成的调用代码失效。
    同时, ClientProxyFactoryBean由于要用到CXF环境,所以要导入CXF的所有包。
    同时,如果是在本项目中调用,则可以直接使用本项目的接口。
    如果在其他项目中调用,仍然需wsimport生成的类,但只需要一个接口。

     

    使用JaxWsServerFactoryBean发布服务: (建议使用此类) 

    JaxWsServerFactoryBean是ServerFactoryBean的子类,也是功能扩展类。
    但在CXF的API文档中没有提供此类API,请通过查看源代码的方式获取此类的帮助。
    此类,必须要在被发布为服务的类上添加@WebService注解,如果不加注解,虽然不
    出错,但也不会对外暴露任何方法。
    使用此类生成的wsdl文件更加规范。
    以下是从它的源代码中找到的对此类的说明。

     

    使用CXF的类发布一个服务:

     

    使用JaxWsProxyFactoryBean客户端调用

    此调用过程与ClientProxyFactoryBean的要求一样,也必须要拥有一个接口。
    此时,仍然可以使用wsimport生成接口,在其他项目的调用。

     

    规范的做法应该是先书写一个接口,如下:

     如果不是使用spring的配置文件发布,可以没有接口文件,但在任何情况下建议拥有接口文件。如果使用spring的配置文件发布,则必须要拥有接口类。

     

    wsdl2java生成客户代码:

    在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。
    先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。
    此工具位于cxf_home/bin目录下。参数与wsimport有所不同。
    它包含以下参数:
    -d参数,指定代码生成的目录。
    -p参数,指定生成的新的包结构。
    需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。
    在命令行执行:
    wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl

     调用端代码:

     

    给服务添加消息拦截器:-这个非常有用:

    LoggingInInterceptor – 信息输入时的拦截器 –请求
    LoggingOutInterceptor –信息输出时的拦截器-响应

     

    给服务器添加拦截器,类似于使用TCP/IP Monitor来捕获SOAP消息的过程。

     使用JavaScript也可以访问WebServie:

    jQuery访问WebService.
    1、在本域准备jquery.js (由于jquery对跨域的请求做了限制,所以jquery仅限于在本域中使用。但为了快速解析XML文件,仍然可以使用jquery当成解析xml文件的工具。)。
    2、通过js发起ajax请求。

     总结:

    如何通过ant发布第一个cxf应用。
    手工建立一个java项目发布cxf的ws.
    Java项目和js访问webService
    加入消息拦截器
    将服务端改为SOAP1.2实现
    SOAP1.1与1.2

     WebService-CXF-Spring基于web的cxf

    开发cxf的web项目: 

    由于cxf的web项目已经集成了Spring所以,cxf的服务类都是在spring的配置文件中完成的。以下是步骤:

    第一步:建立一个web项目。
    第二步:准备所有jar包。将cxf_homelib项目下的所有jar包全部copy到新项目的lib目录下,里面已经包含了spring3.0的jar包。
    第三步:在web.xml中配置cxf的核心servlet,CXFServlet。
    第四步:创建(最好是Copy)cxf-servlet.xml文件。这是一个spring的配置文件。

     web.xml的配置如下:

      

     Cxf-servlet.xml文件说明:

     Cxf-servlet.xml文件,就是一个spring的配置文件。一个空的配置文件如下。

    上面导入的三个配置文件都在cxf.jar的META文件夹中

    在地址栏访问: -配置好空项目后,可以先测试是否可以启动成功:

    http://localhost:9999/cxf_spring/ws

     如果有WebService的存在,则会显示出来,如果没有,则会显示上而的信息。

    如果有WebService的存在,则会显示出来,如果没有,则会显示上而的信息。

    <?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:jaxws="http://cxf.apache.org/jaxws"
        xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://cxf.apache.org/bindings/soap 
                            http://cxf.apache.org/schemas/configuration/soap.xsd
                            http://cxf.apache.org/jaxws 
                            http://cxf.apache.org/schemas/jaxws.xsd
                            http://cxf.apache.org/jaxrs 
                            http://cxf.apache.org/schemas/jaxrs.xsd
                            ">
        <!-- 引入CXF Bean定义如下,早期的版本中使用 -->
        <import resource="classpath:META-INF/cxf/cxf.xml" />
        <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
        <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    
        <!-- 方式一:简单发布,没有接口的发布方式 -->
        <!--
            id:当前服务的唯一标识 address:当前服务对应的请求url implementor:提供服务的类型
        -->
        <jaxws:endpoint id="helloService" address="/hello"
            implementor="com.itheima.service.HelloService">
            <!-- 添加客户端请求的消息拦截器 -->
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
            </jaxws:inInterceptors>
            <!-- 添加服务端响应的消息拦截器 -->
            <jaxws:outInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
            </jaxws:outInterceptors>
        </jaxws:endpoint>
    
        <!-- 方式二:带有接口的发布方式 -->
        <!--
            id:当前服务的唯一标识 address:当前服务对应的请求url serviceClass:接口类型
        -->
        <jaxws:server id="hiService" address="/hi"
            serviceClass="com.itheima.service.IHiService">
            <jaxws:serviceBean>
                <bean class="com.itheima.service.HiServiceImpl" />
            </jaxws:serviceBean>
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
            </jaxws:inInterceptors>
            <jaxws:outInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
            </jaxws:outInterceptors>
        </jaxws:server>
    
        <!-- 发布一个Restful方式的WebService服务 -->
        <bean id="personServiceImpl" class="com.itheima.service.PersonServiceImpl"></bean>
        <jaxrs:server id="personService" address="/p">
            <jaxrs:serviceBeans>
                <ref bean="personServiceImpl" />
            </jaxrs:serviceBeans>
            <jaxrs:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
            </jaxrs:inInterceptors>
            <jaxrs:outInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
            </jaxrs:outInterceptors>
        </jaxrs:server>
    </beans>
    cxf-servlet.xml

    配置发布第一个ws : (jaxb) 

    发布带有接口的配置: (jax-ws)

     

    必须要在声明为serviceClass的接口上声明@WebSerive注解
    因为,要使用了接口,在接口上添加的注解才会有效。

    配置说明: 

    CXFServlet类,通过读取config-location的配置项读取cxf-servlet.xml配置文件。并在内部读取自己的配置文件cxf.xml文件。
    在CXFServlet读取配置文件后,将文件信息全部读取到ApplicationContext的Spring类中。
    以下是它的源代码:

     

    通过配置给服务添加消息拦截器:

    LoggingInInterceptor
    LogginOutInterceptor

     在地址栏访问: 

    http://localhost:9999/cxf2.4_spring_web/ws

     

    Java项目代码调用服务:

    使用纯Java项目调用
    1、根据客户端生成的代码来调用。(优选这种方式)
    请先生成然后在任意的Java项目中调用 。
    2、客户端只拥有一个接口,使用JaxWsProxyFactoryBean来调用。
    因为以下使用了JaxWsProxyFactoryBean,所以,仍然需要CXF的环境,而使用此环境就会造成Jar文件的大量冗余,所以大家要谨慎选择。

     

    在Spring项目中,通过配置文件调用: 

    以下是使用Spring的配置文件调用:
    新建立一个Java项目,并加载cxf的所有包。
    只需要生成的接口文件.
    在classpath下新建立一个ClientBeans.xml文件.

    优点与缺点:
    此种情况,适合于一个Javaweb项目已经集成了Spring。并希望通过CXF配置的方式调用Web服务。
    此种情况,仍然需要导入CXF的大量jar包。
    这种情况也存在一定优点,如可以将外部的Web服务通过配置文件注入(DI)到Action类中。

    建立好以后Java项目如下图 

     

    ClientBeans.xml文件的内容: 

     

    以下是调用代码: 

    关于web项目配置的说明1: 

    如果在项目中仅发布webservice,则可以只配置以下内容。
    同时默认即是读取WEB-INF/cxf-servlet.xml文件,所以是否指定都可以。

     

    关于web项目配置的说明2: 

     但一般情况下,一个web项目,在使用了Spring之后,往往会通过ApplicationContext获取一些服务,此时则必须注册Spring的监听器。即以下代码: 

     

    见备注处,是一个完整的web.xml的配置。 

     关于web项目配置的说明3:

    在上页中出现的重复引入问题,可以修改cxf-servlet.xml文件。
    修改后,CXFServlet类将不能自动加载cxf-servlet.xml文件,此时将导致名为cxf的bean加载不成功。
    为解决此问题必须在重新命名的配置文件中加入以下代码,以启动CXF:
    即:如果你是用contextConfigLocation加载的配置文件,则必须要加入以下代码。

    关于web项目配置的说明4:

    在增加了Spring的监听器之后,即可以使用以下代码在Servlet中获取Spring的配置 : 

    通过JS来调用WebService:

    通过jQuery的ajax方法向服务器发送xml数据。
    必须要先了解xml的数据格式,通过拦截器获取。
    可以从LoggingInInterceptor中获取发出的数据格式。
    可以从LoggingOutInterceptor中获取返回的数据。
    导入jQuery1.5.js文件,放到js/jquery1.5.js 

    通过Ajax访问WebService 

    使用jQuery-本域

    $.ajax({
    url:..
    type:’post’,
    dataType:’xml’,
    contentType:’application/soap+xml;charset=“UTF-8”’
    data:someXml,
    Success:fun()…
    })

     在本域使用jquery访问:  --查询所有用户:

     

    课程回顾:

    什么是WebService?
    在Jdk6上使用Endpoint发布WebService。
    使用wsimport生成客户端代码。及各种监控工具的使用。
    CXF的安装。
    wsdl2java工具的使用。
    CXF与spring进行整合。*
    使用Ajax直接发送SOAP请求。
    View Code

     Web服务为我们带来了什么:SOA

    (这是一种思想,不是简单的代码实现)

     开发基于CXF的RESTFul Webservice

    开发基于CXF的 RESTful WebService
    
    1.创建Web项目并导入CXF的jar
    2.在Web.xml中配置 CXFServlet
        <servlet>
            <servlet-name>cxf</servlet-name>
            <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>cxf</servlet-name>
            <url-pattern>/ws/*</url-pattern>
        </servlet-mapping>
    3.创建实体类 Person
        @XmlRootElement(name = "person")
        public class Person implements Serializable {
            private String id;
            private String name;
            private String description;
            @XmlElement(name = "id")
            public String getId() {
                return id;
            }
            public void setId(String id) {
                this.id = id;
            }
            @XmlElement(name = "name")
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            @XmlElement(name = "description")
            public String getDescription() {
                return description;
            }
            public void setDescription(String description) {
                this.description = description;
            }
        }
    4.定义 PersonService 接口
        //@Produces( { MediaType.APPLICATION_XML })
        @Produces( { MediaType.APPLICATION_JSON }) 
        public interface PersonService extends Serializable {
            @GET
            @Path("/persons")
            public List<Person> getPersons();
    
            @GET
            @Path("/persons/{id}")
            public Person getPerson(@PathParam("id") String id);
        }
    5.提供实现类 PersonServiceImpl
        public class PersonServiceImpl implements PersonService {
            private static final long serialVersionUID = 1L;
            private static Map<String, Person> ps = new HashMap<String, Person>();
            static {
                Person info = new Person();
                p1.setId("1");
                p1.setName("zhangsan");
                p1.setDescription("hello");
    
                Person p1 = new Person();
                p2.setId("2");
                p2.setName("lisi");
                p2.setDescription("lisi hehe");
    
                ps.put(p1.getId(), p1);
                ps.put(p2.getId(), p2);
            }
    
            @Override
            public Person getPerson(String id) {
                return ps.get(id);
            }
    
            @Override
            public List<Person> getPersons() {
                return new ArrayList(ps.values());
            }
        }
    6.提供CXF 的配置文件 cxf-servlet.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:jaxrs="http://cxf.apache.org/jaxrs"
            xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                                http://cxf.apache.org/jaxrs 
                                http://cxf.apache.org/schemas/jaxrs.xsd">
            <import resource="classpath:META-INF/cxf/cxf.xml" />
            <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
            <bean id="personService" class="cn.itcast.cxf.PersonServiceImpl" />
            <jaxrs:server id="RestService" address="/v1">
                <jaxrs:serviceBeans>
                    <ref bean="personService" />
                </jaxrs:serviceBeans>
                <jaxrs:inInterceptors>
                    <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
                </jaxrs:inInterceptors>
                <jaxrs:outInterceptors>
                    <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
                </jaxrs:outInterceptors>
            </jaxrs:server>
        </beans>
    7.访问CXFServlet:http://localhost/CXF_01/ws
    8.通过 URLConnection 访问WebService服务:
            URLConnection conn = new URL("http://localhost/CXF_01/ws/v1/persons").openConnection();
            HttpURLConnection con = (HttpURLConnection) conn;
            con.setRequestMethod("GET");
            int code = con.getResponseCode();
            System.out.println(code);
            InputStream is = con.getInputStream();
            int len = 0;
            byte[] b = new byte[1024];
            StringBuffer sb = new StringBuffer();
            while((len = is.read(b)) != -1){
                String s = new String(b,0,len,"UTF-8");
                sb.append(s);
            }
            System.out.println(sb.toString());
            con.disconnect();
    开发基于CXF的RESTFul Webservice
  • 相关阅读:
    @PostConstruct和 @PreDestroy注解
    【JQuery】,ajax请求中,url出现[Object Object]
    筛法求素数
    母牛的故事
    将一个数拆分
    计算两个日期差
    用二分查找——查找比目标元素略大的索引
    反向输出字符串
    bootstrap table合并单元格(该版本是简单的应用)
    获取访问者IP
  • 原文地址:https://www.cnblogs.com/biaogejiushibiao/p/10351272.html
Copyright © 2020-2023  润新知