CXF学习笔记一:如何创建、发布和访问基于CXF的服务
?主要参考http://cxf.apache.org的相关内容: 1.使用CXF创建服务的基本方法(使用CXF自带的jetty容器) ?? 参考:http://cxf.apache.org/docs/a-simple-jax-ws-service.html 分4步: ① 设置build环境 ② 写服务 ③ 发布服务 ④ 访问服务 ? 1)设置build环境 创建一个新项目,将apache-cxf-2.2.4.zip中lib目录中的下列文件添加到Build Path: commons-logging-1.1.1.jar geronimo-activation_1.1_spec-1.0.2.jar (or Sun's Activation jar) geronimo-annotation_1.0_spec-1.1.1.jar (JSR 250) geronimo-javamail_1.4_spec-1.6.jar (or Sun's JavaMail jar) geronimo-servlet_2.5_spec-1.2.jar (or Sun's Servlet jar) geronimo-ws-metadata_2.0_spec-1.1.2.jar (JSR 181) geronimo-jaxws_2.1_spec-1.0.jar (or Sun's jaxws-api-2.1.jar) geronimo-stax-api_1.0_spec-1.0.1.jar (or other stax-api jar) jaxb-api-2.1.jar jaxb-impl-2.1.12.jar jetty-6.1.21.jar jetty-util-6.1.21.jar neethi-2.0.4.jar saaj-api-1.3.jar saaj-impl-1.3.2.jar wsdl4j-1.6.2.jar wstx-asl-3.2.8.jar XmlSchema-1.4.5.jar xml-resolver-1.2.jar cxf-2.2.4.jar 可选:添加Spring jars,为XML Configuration添加Spring支持。添加的jars如下: aopalliance-1.0.jar spring-core-2.5.5.jar spring-beans-2.5.5.jar spring-context-2.5.5.jar spring-web-2.5.5.jar ? 2)写服务 A)写接口 @WebService public interface HelloWorld { String sayHi(String text); ? ??? // JAX-WS/JAXB 不能直接支持高级用例,处理他们需要写特殊的XmlAdapter ??? String sayHiToUser(User user); ? ??? /* Map 传递 ???? * JAXB 不支持 Maps。它能很好的处理Lists,但Maps不能直接支持他们。 ???? * 他们也需要使用一个XmlAdapter来将maps映射进JAXB可以使用的beans ???? */ ??? @XmlJavaTypeAdapter(IntegerUserMapAdapter.class) ??? Map<Integer,User> getUsers(); } 注意:wsdl会重命名参数的名字,如果不希望这样,应该这样写: @WebService public interface HelloWorld { ??? String sayHi(@WebParam(name="text") String text); } B)写实现: package demo.hw.server; ? import java.util.LinkedHashMap; import java.util.Map; ? import javax.jws.WebService; ? @WebService(endpointInterface = "demo.hw.server.HelloWorld", ??????????? serviceName = "HelloWorld")??? //告诉CXF用哪一个接口创建WSDL public class HelloWorldImpl implements HelloWorld { ??? Map<Integer,User> users = new LinkedHashMap<Integer,User>(); ? ??? public String sayHi(String text) { ??????? System.out.println("sayHi called"); ??????? return "Hello " + text; ??? } ? ??? public String sayHiToUser(User user) { ??????? System.out.println("sayHiToUser called"); ??????? users.put(users.size() + 1,user); ??????? return "Hello "? + user.getName(); ??? } ? ??? public Map<Integer,User> getUsers() { ??????? System.out.println("getUsers called"); ??????? return users; ??? } } ? 3)发布服务(CXF自带Jetty服务器,所以无需Tomcat就可发布) A)使用jws的高层封装: System.out.println("Starting Server"); HelloWorldImpl implementor = new HelloWorldImpl(); String address = "http://localhost:9000/helloWorld"; Endpoint.publish(address,implementor); B)使用下列代码比较精确地控制服务的行为: HelloWorldImpl implementor = new HelloWorldImpl(); JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); svrFactory.setServiceClass(HelloWorld.class);?? //可省,但不建议,因为可能会有些小问题 svrFactory.setAddress("http://localhost:9000/helloWorld"); svrFactory.setServiceBean(implementor); svrFactory.getInInterceptors().add(new LoggingInInterceptor()); svrFactory.getOutInterceptors().add(new LoggingOutInterceptor()); svrFactory.create(); 自此,可以通过http://localhost:9000/helloWorld?wsdl来显示该服务的wsdl LoggingInInterceptor和LoggingOutInterceptor是日志拦截器,用于输入和输出时显示日志,下同。 ? 4)访问服务 A)使用jws的高层封装: //第一个参数是接口实现类包名的反缀 private static final QName SERVICE_NAME = new QName("http://server.hw.demo/","HelloWorld"); private static final QName PORT_NAME= new QName("http://server.hw.demo/","HelloWorldPort"); …… Service service = Service.create(SERVICE_NAME); // Endpoint Address String endpointAddress = "http://localhost:9000/helloWorld"; // Add a port to the Service service.addPort(PORT_NAME,SOAPBinding.SOAP11HTTP_BINDING,endpointAddress); HelloWorld hw = service.getPort(HelloWorld.class); System.out.println(hw.sayHi("World")); B)或者使用下面代码更精确的控制服务: JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.getInInterceptors().add(new LoggingInInterceptor()); factory.getOutInterceptors().add(new LoggingOutInterceptor()); factory.setServiceClass(HelloWorld.class); factory.setAddress("http://localhost:9000/helloWorld"); HelloWorld client = (HelloWorld) factory.create(); ? String reply = client.sayHi("HI"); System.out.println("Server said: " + reply); System.exit(0); ? 2.wsdl2java:从wsdl文档中生成java类,供client使用 设置环境变量CXF_HOME=D:/Program Files/apache-cxf-2.2.4,PATH后加上“;%CXF_HOME%/bin”(可选),然后执行wsdl2java批处理程序,用法如下: 3.定义复杂类型(基本类型如int,String,无须额外定义),参考资料:http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.html 例如: package com.example.customerservice; ? @XmlAccessorType( XmlAccessType.FIELD ) public class Customer {? //自定义类 ??? String name; ??? String/[/] address; ??? int numOrders; ??? double revenue; ??? BigDecimal test; ??? Date birthDate; ??? CustomerType type; //自定义枚举类型 } ? public enum CustomerType { ??? PRIVATE,BUSINESS } //定义Exception @WebFault(name="NoSuchCustomer") @XmlAccessorType( XmlAccessType.FIELD ) public class NoSuchCustomerException extends RuntimeException { /** ?* We only define the fault details here. Additionally each fault has a message ?* that should not be defined separately ?*/ String customerName; }???? //定义Exceptions的默认行为是在后面生成Java code时创建Exception_Exception,所以必须用@WebFault标记来为Bean取一个名字,以与Exception名字相区别 ? @WebService??? //标记本接口为一个服务 public interface CustomerService { public Customer[] getCustomersByName(@WebParam(name="name") String name) throws NoSuchCustomerException;???? //@WebParam标记wsdl中的参数名。如果省略,wsdl将使用arg0代替 } // @WebService还可用来自定义接口名和服务名,分别对应:endpointInterface和serviceName,如: @WebService(endpointInterface = "com.example.customerservice",serviceName = "HelloWorld") ? 生成的WSDL: <xs:complexType name="customer">? //复杂类型 ??? <xs:sequence> ??????? <xs:element minOccurs="0" name="name" type="xs:string"/> ??????? <xs:element maxOccurs="unbounded" minOccurs="0" name="address" nillable="true" type="xs:string"/> ??????? <xs:element name="numOrders" type="xs:int"/> ??????? <xs:element name="revenue" type="xs:double"/> ??????? <xs:element minOccurs="0" name="test" type="xs:decimal"/> ??????? <xs:element minOccurs="0" name="birthDate" type="xs:dateTime"/> ??????? <xs:element minOccurs="0" name="type" type="tns:customerType"/> ??? </xs:sequence> </xs:complexType> minOccurs="0"是可选项,这样可以随时加入新元素,保持兼容性。如果不想要这个选项,可以使用标记@XmlElement(required=true) maxOccurs="unbounded"是为了便于后面的xml重复该元素以形成数组。 ? <xs:simpleType name="customerType">??? //枚举类型 ??? <xs:restriction base="xs:string"> ??????? <xs:enumeration value="PRIVATE"/> ??????? <xs:enumeration value="BUSINESS"/> ??? </xs:restriction> </xs:simpleType> ? <xs:element name="NoSuchCustomer" type="tns:NoSuchCustomer"/> //异常类 ??? <xs:complexType name="NoSuchCustomer"> ??????? <xs:sequence> ??????????? <xs:element name="customerName" nillable="true" type="xs:string"/> ??????? </xs:sequence> ?</xs:complexType> ?<wsdl:message name="NoSuchCustomerException"> ??? <wsdl:part name="NoSuchCustomerException" element="tns:NoSuchCustomer"> ??? </wsdl:part> ?</wsdl:message> // 注意:Element和Message的名字是不同的,这是通过标记@Webfault标记来实现的。也可以让他们同名,但那样会话,生成的Exception的名字会比较丑:NoSuchCustomerException_Exception (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- angularjs – Sails.js Passport.js获取当前登录用户
- 如何在Unix上获取Java中所有挂载文件系统的列表?
- Bootstrap 过渡效果(Transition)插件
- angularjs – 创建更新ng模型的angular-js指令
- 使用spray / scala从post请求获取表单参数
- 可以将scala splat用于任何不是varargs的东西吗?
- Scala中最终课和密封课程有什么区别?
- docker vs docker-compose nginx:在/etc/nginx/nginx.conf
- Vim突出显示复制到剪贴板的字符/单词/行
- angularjs – 从Angular cacheFactory获取密钥