一、概述
1、ApacheCXF项目是由ObjectWeb Celtix和CodeHaus XFire合并成立。ObjectWeb Celtix是
由IONA公司赞助,于2005年成立的开源Java ESB产品,XFire则是业界知名的SOAP堆栈。
合并后的ApacheCXF融合该两个开源项目的功能精华,提供了实现SOA所需要的核心ESB功能框架,
包括SOA服务创建,服务路由,及一系列企业级QoS功能。
2.支持标准
(1)JAX-WS, JSR-181, SAAJ, JAX-RS
(2)SOAP 1.1, 1.2, WS-I BasicProfile, WS-Security, WS-Addressing, WS-RM, WS-Policy
(3)WSDL 1.1
(4)MTOM
3.传输方式,绑定,数据绑定,传送数据格式
(1)绑定: SOAP, REST/HTTP
(2)数据绑定: JAXB 2.x, Aegis, XMLBeans, SDO
(3)传送数据格式: XML, JSON, FastInfoset
(4)传输方式: HTTP, Servlet, JMS
二、基于SOAP发布webservice
(1)pom.xml文件中导入CXF相关包
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-core</artifactId>
- <version>2.6.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-frontend-jaxws</artifactId>
- <version>2.6.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-transports-http</artifactId>
- <version>2.6.2</version>
- </dependency>
(2)web.xml文件中配置
- <servlet>
- <servlet-name>CXFServlet</servlet-name>
- <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>CXFServlet</servlet-name>
- <url-pattern>/cxf/*</url-pattern>
- </servlet-mapping>
(3)创建webService接口UserService
- package com.icsshs.dmis.webservice.soap;
- import javax.jws.WebParam;
- import javax.jws.WebService;
- import com.icsshs.dmis.webservice.soap.response.UserDTO;
- /**
- * JAX-WS2.0的WebService接口定义类 *
- * 使用JAX-WS2.0 annotation设置WSDL中的定义.
- * 使用WSResult及其子类包裹返回结果.
- * 使用DTO传输对象隔绝系统内部领域对象的修改对外系统的影响.
- *
- */
- //name 指明wsdl中<wsdl:portType>元素的名称
- @WebService(name = "UserService", targetNamespace = WsConstants.NS)
- public interface UserService {
- //@WebService是必须的;@WebParam不是必须的。
- //如果没有@WebParam的描述,在wsdl文件内描述的方法中,参数名将变为arg0,arg1…以此类推.
- public String getUserName(@WebParam(name = "userId")String userId);
- public UserDTO getUser(@WebParam(name = "userId")String userId);
- }
UserService接口实现类:
- package com.icsshs.dmis.webservice.soap;
- import javax.jws.WebService;
- import com.icsshs.dmis.webservice.soap.response.UserDTO;
- /**
- * WebService服务端实现类.
- */
- //serviceName指明WSDL中<wsdl:service>与<wsdl:binding>元素的名称,
- //endpointInterface属性指向Interface类全称.
- @WebService(serviceName = "UserService",
- endpointInterface = "com.icsshs.dmis.webservice.soap.UserService",
- targetNamespace = WsConstants.NS)
- public class UserServiceImpl implements UserService {
- @Override
- public UserDTO getUser(String userId) {
- UserDTO dto = new UserDTO();
- dto.setId(Long.parseLong("1001"));
- dto.setLoginName("dongwq");
- dto.setName("张三");
- dto.setEmail("dongwq@qq.com");
- return dto;
- }
- @Override
- public String getUserName(String userId) {
- return "dongwq";
- }
- }
传输的对象UserDTO类:
- package com.icsshs.dmis.webservice.soap.response;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlType;
- import org.apache.commons.lang3.builder.ToStringBuilder;
- import com.icsshs.dmis.webservice.soap.WsConstants;
- /**
- * Web Service传输User信息的DTO.*
- * 只传输外部接口需要的属性.使用JAXB 2.0的annotation标注JAVA-XML映射,尽量使用默认约定.*
- * @XmlRootElement指定User为XML的根元素。User类的属性默认指定映射为@XmlElement。
- * @XmlElement用来定义XML中的子元素。
- * @XmlType-映射一个类或一个枚举类型成一个XML Schema类型
- */
- @XmlRootElement
- @XmlType(name = "User", namespace = WsConstants.NS)
- public class UserDTO {
- private Long id;
- private String loginName;
- private String name;
- private String email;
- // 相关get、set方法省略。
- }
统一命名空间类定义:
- public class WsConstants {
- /**项目内统一的NameSpace定义.**/
- /**wsdl2java生成客户端代码时默认按定义的namespace倒序生成包路径 **/
- public static final String NS = "http://soap.webservice.dmis.icsshs.com";
- }
(4)在spring的applicationContext.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
- http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
- default-lazy-init="true">
- <description>SOAP Web Service配置</description>
- <!--
- 1、访问接口服务:http://localhost:8080/dmis/cxf/soap/userService?wsdl
- 2、访问接口中的方法:
- http://localhost:8080/dmis/cxf/soap/userService/getUserName?userId=aaa
- 或:http://localhost:8080/dmis/cxf/soap/userService/getUserName?arg0=aaa
- -->
- <!-- jax-ws endpoint定义 -->
- <jaxws:endpoint address="/soap/userService">
- <jaxws:implementor ref="userService" />
- </jaxws:endpoint>
- <!-- WebService的实现Bean定义 -->
- <bean id="userService" class="com.icsshs.dmis.webservice.soap.UserServiceImpl" />
- </beans>
(5)启动web应用,测试webservice应用是否发布成功。
访问:http://localhost:8080/dmis/cxf/soap/userService?wsdl
三、基于SOAP的客户端调用
(1)通过代理API调用,依赖于服务端的接口
- /**
- * 通过代理API调用,依赖于服务端的接口
- */
- public static void testClientByProxy(){
- // 调用WebService
- JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
- factory.setServiceClass(UserService.class);
- factory.setAddress("http://localhost:8080/dmis/cxf/soap/userService");
- UserService service = (UserService) factory.create();
- UserDTO user = service.getUser("1001");
- System.out.println(user.getName());
- }
(2)不依赖服务端的接口
- /**
- * 不依赖服务端的接口
- * @throws Exception
- */
- public static void testClient() throws Exception{
- //不依赖服务器端接口来完成调用的,也就是不仅仅能调用Java的接口
- JaxWsDynamicClientFactory clientFactory =
- JaxWsDynamicClientFactory.newInstance();
- Client client = clientFactory.createClient(
- "http://localhost:8080/dmis/cxf/soap/userService?wsdl");
- Object[] result = client.invoke("getUserName", "1001");
- System.out.println(result[0]);
- }
(3)先通过wsdl2Java生成客户端代码,再进行调用
- /**
- * 先通过wsdl2Java生成客户端代码,再进行调用
- */
- public static void testClient2() {
- UserService_Service serivce = new UserService_Service();
- UserService impl = serivce.getUserServiceImplPort();
- String userName = impl.getUserName("1001");
- System.out.println(userName);
- }
四、基于JAX-RS的方式发布WebService
(1)pom.xml文件中导入CXF相关包
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-frontend-jaxrs</artifactId>
- <version>2.6.2</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.jaxrs</groupId>
- <artifactId>jackson-jaxrs-json-provider</artifactId>
- <version>2.0.5</version>
- </dependency>
(2)web.xml文件中配置,同上
- <servlet>
- <servlet-name>CXFServlet</servlet-name>
- <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>CXFServlet</servlet-name>
- <url-pattern>/cxf/*</url-pattern>
- </servlet-mapping>
(3)创建webService接口UserJaxRsService
- package com.icsshs.dmis.webservice.jaxrs;
- import java.io.IOException;
- import javax.ws.rs.GET;
- import javax.ws.rs.POST;
- import javax.ws.rs.Path;
- import javax.ws.rs.PathParam;
- import javax.ws.rs.Produces;
- import javax.ws.rs.WebApplicationException;
- import javax.ws.rs.core.MediaType;
- import javax.ws.rs.core.Response;
- import javax.ws.rs.core.Response.Status;
- import org.springframework.beans.factory.annotation.Autowired;
- import com.icsshs.dmis.entity.bi.BiPerson;
- import com.icsshs.dmis.service.bi.BiService;
- import com.icsshs.dmis.webservice.soap.response.UserDTO;
- @Path("/user")
- public class UserJaxRsService {
- @Autowired
- private BiService biService;//业务系统类接口,省略
- @GET
- @Path("/{personCode}.xml")
- @Produces(MediaType.APPLICATION_XML)
- public UserDTO getAsXml(@PathParam("personCode") String personCode) {
- BiPerson person = biService.findBiPersonByPersonCode(personCode);
- if (person == null) {
- String message = "用户不存在(id:" + personCode + ")";
- throw buildException(Status.NOT_FOUND, message);
- }
- UserDTO dto = new UserDTO();
- dto.setName(person.getPersonName());
- dto.setLoginName(person.getR1PersonId());
- return dto;
- }
- @GET
- @Path("/{personCode}.json")
- @Produces(MediaType.APPLICATION_JSON)
- public UserDTO getAsJson(@PathParam("personCode") String personCode) {
- BiPerson person = biService.findBiPersonByPersonCode(personCode);
- if (personCode == null) {
- String message = "用户不存在(id:" + personCode + ")";
- throw buildException(Status.NOT_FOUND, message);
- }
- UserDTO dto = new UserDTO();
- dto.setName(person.getPersonName());
- dto.setLoginName(person.getR1PersonId());
- return dto;
- }
- @POST
- @Path("/addUser")
- @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- public UserDTO addUser(UserDTO user) throws IOException {
- System.out.println(user);
- user.setName("jojo##12321321");
- return user;
- }
- private WebApplicationException buildException(Status status, String message){
- return new WebApplicationException(Response.status(status).entity(
- message).type(MediaType.TEXT_PLAIN).build());
- }
- }
(4)在spring的applicationContext.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://cxf.apache.org/jaxrs
- http://cxf.apache.org/schemas/jaxrs.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
- default-lazy-init="true">
- <description>Apache CXF的Restful Web Service配置</description>
- <!-- jax-rs endpoint定义 -->
- <jaxrs:server id="serviceContainer" address="/jaxrs">
- <jaxrs:serviceBeans>
- <ref bean="userJaxRsService" />
- </jaxrs:serviceBeans>
- <jaxrs:providers>
- <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" />
- </jaxrs:providers>
- </jaxrs:server>
- <!-- WebService的实现Bean定义 -->
- <bean id="userJaxRsService"
- class="com.icsshs.dmis.webservice.jaxrs.UserJaxRsService" />
- </beans>
(5)启动web应用,测试webservice应用是否发布成功。
访问:http://localhost:8080/dmis/cxf/jaxrs?_wadl
可以通过http://localhost:8080/dmis/cxf/jaxrs/15811006.json直接访问获取数据
五、基于JAX-RS的Restful客户端调用
(1)依赖服务端的接口,通过代理API调用
- /**
- * 依赖服务端的接口
- * 代理API允许你使用RESTful服务的资源类和接口。
- * 代理类是客户端直接调用接口方法,使用户不需要手工创建HTTP请求。
- */
- public static void testClientByProxy(){
- UserJaxRsService store = JAXRSClientFactory
- .create("http://localhost:8080/dmis/cxf/jaxrs",
- UserJaxRsService.class);
- System.out.println(store.getAsXml("15811006"));
- }
(2)通过HTTP客户端进行调用
- /**
- * HTTP客户端
- * 使用org.apache.cxf.jaxrs.client.WebClient调用RESTful服务
- *
- */
- public static void testClientByHttp(){
- String format = MediaType.APPLICATION_XML;
- WebClient client = WebClient.create("http://localhost:8080/dmis/cxf/jaxrs");
- client.path("/user/15811006.xml").accept(format).type(format);
- UserDTO user = client.get(UserDTO.class);
- System.out.println("userName: " + user.getName());
- }
3、通过HTTP客户端进行调用,并传递对象
- /**
- * HTTP客户端(传递对象)
- *
- */
- public static void testClientByObject(){
- String format = MediaType.APPLICATION_XML;
- System.out.println("testAddCategory called with format " );
- WebClient client = WebClient.create("http://localhost:8080/dmis/cxf/jaxrs");
- client.path("/user/addUser").accept(format).type(format);
- UserDTO userDTO = new UserDTO();
- userDTO.setName("userName");
- userDTO.setLoginName("loginName");
- UserDTO returnUser = client.post(userDTO,UserDTO.class);
- System.out.println("userName: " + returnUser.getName()
- +" lgoinName: "+returnUser.getLoginName());
- }
注:HTTP客户端调用时,如果不依赖于服务端接口,可通过wsdl2java或wadl2java生成客户端代码。