1.首先从CXF的官网下载jar包
http://cxf.apache.org/
2.写接口
package com.tjsoft.webservice;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.WebService;
@WebService(name="HelloWorld")
public interface HelloWorld {
@WebMethod(operationName="sayHello")
public String sayHello(String name);
}
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 class HelloWorldImpi implements HelloWorld {
public String sayHello(String name) {
System.out.println("调用WebService");
return 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>
<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
<?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"
xsi:schemaLocation=" http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans
<beans xmlns=" http://www.springframework.org/schema/beans"
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws=" http://cxf.apache.org/jaxws"
xsi:schemaLocation=" http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans
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>
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>
<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>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>
7.applicationcontext.xml 或者自己写一个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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schema/jaxws.xsd">
<beans xmlns=" http://www.springframework.org/schema/beans"
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws=" http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schema/jaxws.xsd">
<bean id="client" class="com.tjsoft.webservice.HelloWorld"
factory-bean="clientFactory" factory-method="create" />
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>
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 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);
}
}
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)"/>
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>
<!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
public interface IResultService
方法就省略
2.实现类
@WebService(endpointInterface="com.tjsoft.module.activity.service.IResultService")
public class ResultServiceImp implements 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")
@XmlType(name = "TBusiActivity")
上面只是单个表的操作
但是我们的项目中不仅有多个表的查询还有一对多的关系
本人根据jaxb 中有个elements 的例子意外的弄成功了,但我现在还是不理解
自定义一个类型
package com.tjsoft.module.activity.schem;
import java.util.ArrayList;
import java.util.List;
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 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" })
@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;
}
} 注意这里的包不要到错
@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)
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)
})
@XmlElement(name="LabelCount",type=com.tjsoft.module.activity.schem.LabelCount.class)
})
这个就可以解决,但是你必须把它暴露出去,也就是写一个方法返回一个自定义类型实现类可以什么都不用写
这就是我搞Webservice 遇到的难题。