关于CXF

1.首先从CXF的官网下载jar包 http://cxf.apache.org/
2.写接口
package com.tjsoft.webservice;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(name="HelloWorld")
public interface HelloWorld {
   @WebMethod(operationName="sayHello")
   public String sayHello(String name); 
}
3.接口的实现类
package com.tjsoft.webservice;
import javax.jws.WebService;
@WebService(endpointInterface="com.tjsoft.webservice.HelloWorld")
public class HelloWorldImpi implements HelloWorld {
 public String sayHello(String name) {
  System.out.println("调用WebService"); 
  return name+"说:你们好!!";
 }
}
4.配置Web.xml
 <servlet>
    <display-name>CXF Servlet</display-name>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
     <servlet-name>CXFServlet</servlet-name>
     <url-pattern>/services/*</url-pattern>
   </servlet-mapping>
5.配置webservice.xml
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
    default-autowire="byName" default-lazy-init="true">
    <description>基于Apache CXF的Web Service配置文件</description>
   
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-javascript-client.xml"/>
   
    <bean id="helloWorldImpl" class="com.tjsoft.webservice.HelloWorldImpi"/>
    <jaxws:endpoint id="helloWorld" implementor="#helloWorldImpl"
        address="/HelloWorld"/>
</beans>
这样服务器的开发就结束了
在开发客户端的时候一定要先把接口打包成一个jar 包然后导入到作为客户端的一个Web 工程下
6.客户端Web.xml 文件的配置
 <servlet>
      <display-name>CXF Servlet</display-name>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>
            org.apache.cxf.transport.servlet.CXFServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/webservice/*</url-pattern>
    </servlet-mapping>
7.applicationcontext.xml 或者自己写一个xml 文件
    <bean id="client" class="com.tjsoft.webservice.HelloWorld"
        factory-bean="clientFactory" factory-method="create" />
    <bean id="clientFactory"
        class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
        <property name="serviceClass" value="com.tjsoft.webservice.HelloWorld" />
        <property name="address" value=" http://192.9.207.230:8080/dzmd/services/HelloWorld" />  
    </bean>    
</beans>
8.客户端的测试类
package com.tjsoft;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.tjsoft.webservice.HelloWorld;
public final class ClientServer{
    private ClientServer(){
     
    }
    public static void main(String args[]) throws Exception{ 
     
     String str="WebRoot/WEB-INF/applicationContext.xml";
     
     //String path="WebRoot/WEB-INF/applicationContext*.xml";
     
     ApplicationContext context = new FileSystemXmlApplicationContext(str);
          
        HelloWorld client = (HelloWorld) context.getBean("client");    
       
        String response = client.sayHello("邓建利");             
       
        System.out.println("结果: " + response);       
           
        System.exit(0);              
    }    
}
这样一个简单的WebService 就完成了。但是当客户端是flex 调用Webservice 该怎么写呢?
下面就是客户端(flex )调用WebService 的例子
<mx:WebService id="webService2" wsdl=" http://192.9.207.230:8080/dzmd/services/result?wsdl"
showBusyCursor="true"  useProxy="false"  result="answerResult(event)" fault="faultHandler(event)"/> 
本来以为这样就可以了但是报了个这样的错误
RPC Fault faultString="Security error accessing url" faultCode="Channel.Security.Error" faultDetail="Unable to load WSDL. 
If currently online, please verify the URI and/or format of the WSDL 
后来在网上查了下资料说是flex 安全箱的问题
解决方法是:在WebService 容器的根目录下添加一个crossdomain.xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM " http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <site-control permitted-cross-domain-policies="all" />
  <allow-access-from domain="*" to-ports="8080" secure="false" />
  <allow-http-request-headers-from domain="*" headers="*" secure="false" />  
</cross-domain-policy> 
一开始我把这个文件放在了工程下的根目录,放错了位置。害的我搞了半天具体位置是放在Tomcate webapps 目录下的ROOT 文件夹下面而且文件名称必须是crossdomain.xml
这样客户端就可以访问了。
上面是一个很小的demo 。
但是项目就不那么简单了
下面是项目中的demo
1.接口
@WebService(name = "result")  
public interface IResultService
方法就省略
2.实现类
@WebService(endpointInterface="com.tjsoft.module.activity.service.IResultService")
public class ResultServiceImp implements IResultService
如果方法里是查询一个类的po 不管是返回一个List  还是一个po 的对象都可以。这里要注意一点就是
分离entity类与web service接口间的耦合,隔绝entity类的修改对接口的影响. 
使用JAXB 2.0的annotation标注JAVA-XML映射,尽量使用默认约定 这句话的理解。
这句话的意思就是在每个po 类的前面添加这样一句话
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)    
@XmlType(name = "TBusiActivity")
上面只是单个表的操作
但是我们的项目中不仅有多个表的查询还有一对多的关系
本人根据jaxb 中有个elements 的例子意外的弄成功了,但我现在还是不理解
自定义一个类型
package com.tjsoft.module.activity.schem;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlType;
import com.tjsoft.model.sys.TBusiActivity; 
@XmlAccessorType(XmlAccessType.FIELD)   
@XmlType(name = "listObject", propOrder = { "list" })
public class ListObject {   
 @XmlElements({
  @XmlElement(name="TBusiActivity",type=com.tjsoft.model.sys.TBusiActivity.class),
  @XmlElement(name="TBusiSubject",type=com.tjsoft.model.sys.TBusiSubject.class),
  @XmlElement(name="TBusiSubjectanswer",type=com.tjsoft.model.sys.TBusiSubjectanswer.class),
  @XmlElement(name="TBusiSurveyform",type=com.tjsoft.model.sys.TBusiSurveyform.class),   
  @XmlElement(name="TBusiMdresult",type=com.tjsoft.model.sys.TBusiMdresult.class)
 })  
    protected List<TBusiActivity> list;          
    public List<TBusiActivity> getList() {       
        if (list == null) {       
            list = new ArrayList<TBusiActivity>();          
        }   
        return this.list;       
    }      
      
    public void setList(List<TBusiActivity> list) {      
        this.list = list;   
    }       
} 注意这里的包不要到错
这就好比一个入口一样把每个po都映射了一下 我是这样解决的
这里还涉及到一对多的关系
解决方法如下:
在另一个po里面有与之关联的主键po对象用@XmlTransient 把它注释掉
这样就可以了
如果不注释会包这样的一个错
org.apache.cxf.interceptor.Fault: Marshalling Error: A cycle is detected in the object graph. This will cause infinitely deep XML: com.tjsoft.model.sys.TBusiActivity@60310f -> com.tjsoft.model.sys.TBusiQuestionnaire@12e18d7 -> com.tjsoft.model.sys.TBusiActivity@60310f
at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:159)
还有一个错误也是经常见到
org.apache.cxf.interceptor.Fault: Marshalling Error: com.tjsoft.module.activity.schem.LabelCount is not known to this context
这个好像就是没有与之匹配的类
解决这个方法就是上面自定义一个类型用
@XmlElements({    
  @XmlElement(name="LabelCount",type=com.tjsoft.module.activity.schem.LabelCount.class)
 })  
这个就可以解决,但是你必须把它暴露出去,也就是写一个方法返回一个自定义类型实现类可以什么都不用写
这就是我搞Webservice 遇到的难题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值