加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

CXF 开发 WebService

发布时间:2020-12-16 23:12:39 所属栏目:安全 来源:网络整理
导读:什么是CXF: Apache CXF = Celtix + Xfire ????????????支持多种协议: ????????????SOAP1.1,1.2 ????????????XML/HTTP ????????????CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。????????????????????C,c+

什么是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的其他支持项目:

Ant

Tomcat

并设置以下环境变量:

????????????JAVA_HOME ?

????????????CXF_HOME

????????????ANT_HOME

????????????CATALINA_HOME

????????????Path = %JAVA_HOME%bin;%CXF_HOME%bin;%CATALINA_HOME%bin;%ANT_HOME%bin

????????????CLASSPATH=.;%CXF_HOME%libcxf-manifest.jar;.buildclasses

在Eclipse中开发CXF的JavaSE应用:

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

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

CXF发布服务的类:

用两个不同的类发布应用:

????????????ServerFactoryBean ? -- FacotryBean

????????????JaxWsServerFactoryBean(建议使用此类)

使用ServerFactoryBean发布服务:

复制代码

/**
 * 使用ServerFactoryBean发布CXF的javase应用
 * @author zhaoqx
 *
 */
public class HelloService {
     
    public String sayHello(String name){
        System.out.println("sayHello called...");
        return "hello " + name;
    }
    static void main(String[] args) {
        ServerFactoryBean bean = new ServerFactoryBean();
        bean.setAddress("http://192.168.1.24:9999/Hello");
        bean.setServiceClass(HelloService.class);
        bean.setServiceBean(new HelloService());
        bean.create();
        System.err.print("启动成功");
    }
}

复制代码

使用ClientProxyFactoryBean客户端调用

使用ServerFactoryBean发布服务以后,在没有接口的情况下,可以使用wsimport生成的客户端代码调用成功。

但如果要使用ClientProxyFactoryBean客户端去调用服务器,则必须要先在服务器端创建一个接口。(一直以来,Spring都要 求面向接口编程,而cxf与Spring能很好的整合,也就在此。),所以,必须要重写服务器端的代码。这将导致刚才使用wsimport生成的调用代码 失效。

同时, ClientProxyFactoryBean由于要用到CXF环境,所以要导入CXF的所有包。

同时,如果是在本项目中调用,则可以直接使用本项目的接口。

如果在其他项目中调用,仍然需wsimport生成的类,但只需要一个接口。

0

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

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

?

复制代码

@WebService
//@javax.xml.ws.BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
class HiService {
    public String sayHi(String name){
        System.out.println("服务调用");
        return "Hi"+name;
    }
    void main(String[] args) {
        JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();
        bean.setAddress("http://localhost:9999/two");
        bean.setServiceClass(HiService.new HiService());
        bean.create();
        System.err.print("服务启动成功");
    }
}
使用JaxWsProxyFactoryBean客户端调用:

此调用过程与ClientProxyFactoryBean的要求一样,也必须要拥有一个接口。

此时,仍然可以使用wsimport生成接口,在其他项目的调用。

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

@WebService
interface IHelloService {
    public String sayHello(String name);
}

class IHelloServiceImpl implements IHelloService { public String sayHello(String name) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(new Date())+"=== hello=====" + name; } new JaxWsServerFactoryBean(); bean.setAddress("http://192.168.1.24:8888/sayHi"); bean.setServiceClass(IHelloService.new IHelloServiceImpl()); 加入请求消息拦截器 bean.getInInterceptors().add(new LoggingInInterceptor()); 加入响应消息拦截器 bean.getOutInterceptors().add(new LoggingOutInterceptor()); bean.create(); System.err.print("服务启动成功"); } }

wsdl2java生成客户代码:

在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。

先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。

此工具位于cxf_home/bin目录下。参数与wsimport有所不同。

它包含以下参数:

-d参数,指定代码生成的目录。

-p参数,指定生成的新的包结构。

需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。

在命令行执行:

wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl

?调用端代码:?

使用JavaScript也可以访问WebServie:

复制代码

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用jquery的ajax调用Web服务 </title>
    <script type="text/javascript" src="js/jquery-1.6.2.js"></script>
    <script type="text/javascript">
        $(function(){
            $("#but1").click(function(){
                指定访问服务的地址
                var wsUrl = "http://localhost:8090/CXF03/cxf/hi";
                构造请求体
                var soap = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://kaiyi/"><arg0>abc</arg0></ns2:sayHi></soap:Body></soap:Envelope>';
                $.ajax({
                        url:wsUrl,type:'post',dataType:'xml',contentType:'text/xml;charset=UTF-8',data:soap,success:function(data){
                            alert('OK!');
                            var o = $(data);
                            alert(o.find('return').eq(0).text());
                        },error:function(){
                            alert('error!');
                        }
                        });
            });
        });
    </script>
  </head>
   
  <body>
    <input type="button" value="发送jquery的ajax请求" id="but1">
  </body>
</html>
以上均是非WEB的开发下面介绍基于web的cxf

由于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的配置文件。

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: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" />
 
    <!-- 通过spring配置文件发布CXF的服务 -->
 
    <!-- 第一种发布方式:没有接口的发布(简单发布) -->
    <!-- 
        id:唯一标识
        address:访问url
        implementor:提供服务的类型 
     -->
    <jaxws:endpoint id="helloService" address="/hello"
        implementor="kaiyi.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>
     
    <!-- 第二种发布方式:带有接口的发布 -->
    <jaxws:server id="hiService" address="/hi" serviceClass="kaiyi.IHiService">
        <jaxws:serviceBean>
            <!-- 提供服务的实现类 -->
            <bean class="kaiyi.IHiServiceImpl"></bean>
        </jaxws:serviceBean>
        <!-- 加入消息拦截器  -->
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
        </jaxws:outInterceptors>
    </jaxws:server>
     
    <!-- 配置restful方式的web服务 -->
    <bean id="ps" class="restful.PersonServiceImpl"></bean>
    <jaxrs:server id="personService" address="/p">
        <jaxrs:serviceBeans>
            <ref bean="ps"/>
        </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>
web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 通过上下文参数指定spring配置文件的位置 --> context-param> param-name>contextConfigLocation</param-value>classpath:cxf-servlet.xml> listenerlistener-class>org.springframework.web.context.ContextLoaderListener 配置CXF框架的核心Servlet servletservlet-name>cxfservlet-class>org.apache.cxf.transport.servlet.CXFServlet 通过初始化参数指定配置文件的位置 --> <init-param> <param-name>config-location</param-name> <param-value>classpath:cxf-servlet.xml</param-value> </init-param>--> > servlet-mappingurl-pattern>/cxf/*> welcome-file-listwelcome-file>index.jsp> > web-app>
这是我的包结构

*/ @WebService return "hello " + name; } }

复制代码

package kaiyi; import javax.jws.WebService; @WebService interface IHiService { public String sayHi(String name); }
class IHiServiceImpl implements IHiService{ public String sayHi(String name) { System.out.println("sayHi...."); return "hi " + name; } }
在地址栏访问:

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类中。

ClientBeans.xml文件的内容:

beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" 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" 配置客户端bean id:唯一标识 address:请求的服务地址 serviceClass:客户端接口 jaxws:client id="hiService" address="http://localhost:8090/CXF03/cxf/hi" serviceClass="kaiyi.IHiService"></jaxws:client> beans 以下是调用代码:

package test; import kaiyi.IHiService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; class test { void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("ClientBeans.xml"); IHiService ihi = (IHiService) ctx.getBean("hiService"); ihi.sayHi("abc"); System.out.println(ihi.getClass().getName()); } }
通过JS来调用WebService:

POJO类:

package pojo; import java.io.Serializable; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "person") class Person implements Serializable{ * */ private final long serialVersionUID = 1L; private String id; private String name; private String desc; @XmlElement(name = "id") public String getId() { return id; } void setId(String id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } void setName(String name) { this.name = name; } @XmlElement(name = "desc") public String getDesc() { return desc; } void setDesc(String desc) { this.desc = desc; } @Override public String toString() { return "Person [desc=" + desc + ",id=" + id + ",name=" + name + "]"; } }
现在一般来说用URL的方式调用restful服务比较流行:


它与WSDL方式完全不同,采用的是一种新型的方式,企业开发使用较为常见:

Available RESTful services:

Endpoint address: http://localhost:8090/CXF03/cxf/p
WADL : http://localhost:8090/CXF03/cxf/p?_wadl&type=xml

访问后返回的是json或者XML数据

此种方式只需要在cxf-servlet.xml配置一下即可:

配置restful方式的web服务 bean ="ps" class="restful.PersonServiceImpl"beanjaxrs:server ="personService"="/p"jaxrs:serviceBeans> ref ="ps"/> jaxrs:inInterceptorsclass="org.apache.cxf.interceptor.LoggingInInterceptor"jaxrs:outInterceptors="org.apache.cxf.interceptor.LoggingOutInterceptor"jaxrs:server 以下是访问方式:

import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.List; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.junit.Test; import pojo.Person; 使用URL的方式调用restful服务 class UrlConnectionTest { @Test void test1() throws Exception { String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons/id0"; URL url = new URL(wsUrl); URLConnection conn = url.openConnection(); HttpURLConnection con = (HttpURLConnection)conn; con.setRequestMethod("GET"); int code = con.getResponseCode(); if(code == 200){ InputStream in = con.getInputStream(); byte[] b = new byte[1024]; int len = 0; StringBuffer sb = new StringBuffer(); while((len=in.read(b))!=-1){ String s = new String(b,len,"UTF-8"); sb.append(s); } String json = sb.toString(); JSONObject o = JSONObject.fromObject(json); json = o.getString("person").toString(); 将String转换为Person对象 Person person = (Person) JSONObject.toBean(JSONObject.fromObject(json),Person.class); System.out.println("----"+person); } con.disconnect(); } @Test void test2() throws Exception { String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons"; URL url = ); sb.append(s); } String json = sb.toString(); JSONObject o = JSONObject.fromObject(json); Object obj = o.get("person"); json = obj.toString(); List<Person> list = (List<Person>)JSONArray.toCollection(JSONArray.fromObject(json),255); font-size:12px!important; line-height:1.5!important">class); for(Person p:list){ System.out.println(p); } } con.disconnect(); } }

我们可以根据被调用服务的接口上的注解来决定返回值的数据格式

//@Produces( { MediaType.APPLICATION_XML })

@Produces( { MediaType.APPLICATION_JSON })

public interface IPersonService extends Serializable?

以下是服务代码:

package restful; import java.io.Serializable; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Produces( { MediaType.APPLICATION_XML }) @Produces( { MediaType.APPLICATION_JSON }) interface IPersonService extends Serializable { @GET @Path(value="/persons/{id}") public Person findPersonById( @PathParam("id") String id); @GET @Path(value="/persons") public List<Person> findAllPerson(); }

package restful; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import pojo.Person; class PersonServiceImpl implements IPersonService { static Map<String,Person> ps = new HashMap<String,Person>(); static { for(int i=0;i<5;i++){ Person p = new Person(); p.setId("id" + i); p.setName("person" + i); p.setDesc("desc" + i); ps.put(p.getId(),p); } } public List<Person> findAllPerson() { return new ArrayList<Person>(ps.values()); } public Person findPersonById(String id) { return ps.get(id); } }
以下是调用代码:

for(Person p:list){ System.out.println(p); } } con.disconnect(); }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读