WebService与Apache-CXF
1. WebService与CXF简介
1.1什么是WebService
1.2什么是CXF
Apache CXF = Celtix + XFire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。Apache CXF已经是一个正式的Apache顶级项目。
1.3 CXF WebService 开发,主要分为两种服务提供方式WS 、RS
1.3.1 JAX-WS
JAX-WS:全称是JavaTM API forXML-Based Web Services
1.3.2 JAX-RS
JAX-RS :全称是 JavaTM API forRESTful Web Services
JAX-RS是JAVA EE6 引入的一个新技术。 JAX-RS即Java API for RESTful Web Services,是一个Java 编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建Web服务。JAX-RS使用了Java SE5引入的Java注解来简化Web服务的客户端和服务端的开发和部署。
2. WS方式开发
2.1 WS方式单独使用
1)创建maven-jar项目(自行创建)
2)导入pom依赖,以及log4j.properties文件
<!-- jaxws相关依赖 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 测试使用的jetty服务器 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 日志相关依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<!-- log4j配置文件 -->
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
3)测试准备工作
实体类 : User (属性:String name,List<Car>)、Car(属性:String carName,Double price)
接口:
package cn.itcast.service; import java.util.List; import javax.jws.WebMethod; import javax.jws.WebService; @WebService public interface IUserService { @WebMethod String sayHello(String name); @WebMethod List<Car> findCarByUser(User user); }
接口实现类:
package cn.itcast.service; import java.util.ArrayList; import java.util.List; import javax.jws.WebService; @WebService(endpointInterface="cn.itcast.service.IUserService",serviceName="userService") public class UserServiceImpl implements IUserService { @Override public String sayHello(String name) { return "hello: "+name; } @Override public List<Car> findCarByUser(User user) { ArrayList<Car> list = new ArrayList<>(); if ("xiaoming".equals(user.getName())) { Car car1 = new Car(); car1.setId(1); car1.setCarName("falali1"); car1.setPrice(10000000.1); Car car2 = new Car(); car2.setId(2); car2.setCarName("falali2"); car2.setPrice(10000000.2); Car car3 = new Car(); car3.setId(3); car3.setCarName("falali3"); car3.setPrice(10000000.3); list.add(car1); list.add(car2); list.add(car3); } return list; } }
远程服务启动类
package cn.itcast.service;
import javax.xml.ws.Endpoint;
public class Service {
public static void main(String[] args) {
//实例化服务
IUserService userService = new UserServiceImpl();
//设置地址
String address="http://localhost:9999/userService";
//建立服务
Endpoint.publish(address, userService);
//服务建立提示
System.out.println("服务已经启动");
}
}
客户端代码编写(远程调用服务)
package cn.itcast.client; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import cn.itcast.service.IUserService; import cn.itcast.service.User; public class Client { public static void main(String[] args) { //创建并设置接口调用 JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); jaxWsProxyFactoryBean.setAddress("http://localhost:9999/userService"); jaxWsProxyFactoryBean.setServiceClass(IUserService.class);
//添加日志监控
jaxWsProxyFactoryBean.getInInterceptors().add(new LoggingInInterceptor());
jaxWsProxyFactoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
//创建接口代理类 IUserService proxy = (IUserService) jaxWsProxyFactoryBean.create(); //远程调用服务 System.out.println(proxy.sayHello("小明")); User user = new User(); user.setName("xiaoming"); System.out.println(proxy.findCarByUser(user)); } }
2.2 WS方式与Spring整合
1)创建maven项目:服务端和客户端两个web项目(自行创建)
2)导入pom依赖,web.xml配置,spring配置文件,以及log4j.properties文件(日志文件内容如上)
<!-- jaxws相关依赖 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.0.1</version> </dependency> <!-- Spring依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.7</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.1.7</version> </dependency> <!-- 单元测试 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.1.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- spring配置文件位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext*.xml</param-value> </context-param> <!-- spring核心监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- CXF基于WEB访问 :服务端需要、客户端不需要此配置 --> <servlet> <servlet-name>CXFService</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFService</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
spring配置文件
服务端:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:server id="userService" address="/userService" serviceClass="cn.itcast.service.IUserService"> <jaxws:serviceBean> <bean class="cn.itcast.service.UserServiceImpl"/> </jaxws:serviceBean> </jaxws:server> </beans>
客户端:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:client id="userServiceClient" serviceClass="cn.itcast.service.IUserService" address="http://127.0.0.1:9998/webservice_spring/services/userService"> <!-- 输入消息日志记录 --> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/> </jaxws:inInterceptors> <!-- 输出消息日志记录 -->
<jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/> </jaxws:outInterceptors> </jaxws:client> </beans>
测试:
服务端:将实体类、接口还有接口的实现copy过来,启动项目
客户端:将实体类、接口copy过来,创建一个测试类Client
package cn.itcast.service; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:spring/applicationContext*.xml") public class Client { @Autowired private IUserService userService; @Test public void name() { System.out.println(userService.sayHello("nima")); User user = new User(); user.setName("xiaoming"); System.out.println(userService.findCarByUser(user)); } }
3. RS方式开发
什么是Restful自行百度
3.1 RS方式单独使用
1)创建maven-jar项目(自行创建)
2)导入pom依赖,以及log4j.properties文件
<dependencies> <!-- jaxws相关依赖 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.0.1</version> </dependency> <!-- cxf-client --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>3.0.1</version> </dependency> <!-- 日志相关依赖 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <showWarnings>true</showWarnings> </configuration> </plugin> </plugins> </build>
<!-- log4j配置文件 -->
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
3)测试准备工作
实体类 : User (属性:String name,List<Car>)、Car(属性:String carName,Double price) 实体类上添加注解@XmlRootElement(name="User")和@XmlRootElement(name="Car"),表示实体类可序列化


接口类
package com.fbc0928.service; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path("/userService") @Produces("*/*") @Consumes({"application/xml","application/json"}) public interface IUserService { @POST @Path("/user") void save(User user); @PUT @Path("/user") void update(User user); @DELETE @Path("/user/{id}") void delete(@PathParam("id")Integer id); @GET @Path("/user/{id}") User findOne(@PathParam("id")Integer id); @GET @Path("/user") List<User> findAll(); }
接口实现类
package com.fbc0928.service; import java.util.ArrayList; import java.util.List; import javax.jws.WebService; @WebService(endpointInterface="cn.itcast.service.IUserService",serviceName="userService") public class UserServiceImpl implements IUserService { @Override public void save(User user) { System.out.println("保存成功"); System.out.println(user); } @Override public void update(User user) { System.out.println("更新成功"); System.out.println(user); } @Override public void delete(Integer id) { System.out.println("删除成功"); System.out.println(id); } @Override public User findOne(Integer id) { User user = new User(); user.setId(id); user.setName("aaa"); user.setCity("beijing"); return user; } @Override public List<User> findAll() { ArrayList<User> users = new ArrayList<>(); User user1 = new User(); user1.setId(1); user1.setName("aaa"); user1.setCity("beijing"); User user2 = new User(); user2.setId(2); user2.setName("bbb"); user2.setCity("beijing"); User user3 = new User(); user3.setId(3); user3.setName("ccc"); user3.setCity("beijing"); users.add(user1); users.add(user2); users.add(user3); return users; } }
服务端启动类
public class Service { public static void main(String[] args) { IUserService userService = new UserServiceImpl(); //创建服务 JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean(); jaxrsServerFactoryBean.setResourceClasses(User.class,Car.class); jaxrsServerFactoryBean.setServiceBean(userService); jaxrsServerFactoryBean.setAddress("http://127.0.0.1:9997"); //发布服务 jaxrsServerFactoryBean.create(); System.out.println("服务已启动"); } }
客户端测试类
public class Client { public static void main(String[] args) {
//调用void save(User user); User user1 = new User(); user1.setName("1只宝宝"); WebClient.create("http://127.0.0.1:9997/userService/user") .type(MediaType.APPLICATION_XML).post(user1);
//调用void update(User user); User user2 = new User(); user2.setName("2只宝宝"); WebClient.create("http://127.0.0.1:9997/userService/user") .type(MediaType.APPLICATION_XML).put(user2);
//调用void delete(@PathParam("id")Integer id); Integer id1=1; WebClient.create("http://127.0.0.1:9997/userService/user/"+id1) .type(MediaType.APPLICATION_XML).delete();
//调用User findOne(@PathParam("id")Integer id); Integer id2=2; User user = WebClient.create("http://127.0.0.1:9997/userService/user/"+id2) .type(MediaType.APPLICATION_XML).get(User.class); System.out.println(user);
//调用List<User> findAll(); Collection<? extends User> collection = WebClient .create("http://127.0.0.1:9997/userService/user") .accept(MediaType.APPLICATION_XML) .getCollection(User.class); System.out.println(collection); } }
3.2 RS方式与Spring整合
1)创建maven-web项目(客户端和服务端两个项目,自行创建)
2)导入pom依赖,log4j配置文件(自己到上面复制),配置web.xml配置文件,spring配置文件
服务端:
pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fbc0928</groupId> <artifactId>jaxrs_spring_server</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!-- jaxws相关依赖 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.3.7</version> </dependency> <!-- Spring依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.1.7.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <showWarnings>true</showWarnings> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>9996</port> </configuration> </plugin> </plugins> </build> </project>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- spring配置文件位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext*.xml</param-value> </context-param> <!-- spring核心监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- CXF基于WEB访问 --> <servlet> <servlet-name>CXFService</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFService</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
applicationContext-jawrs.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <jaxrs:server id="userService" address="/userService"> <jaxrs:serviceBeans> <bean class="com.fbc0928.service.UserServiceImpl" /> </jaxrs:serviceBeans> </jaxrs:server> </beans>
客户端:客户端的访问方式和未整合一样,没有提供jsxrs方式的客户端整合,使用上面的客户端测试类
public class Client { public static void main(String[] args) { //调用void save(User user); User user1 = new User(); user1.setName("1只宝宝"); WebClient.create("http://127.0.0.1:9997/userService/user") .type(MediaType.APPLICATION_XML).post(user1); //调用void update(User user); User user2 = new User(); user2.setName("2只宝宝"); WebClient.create("http://127.0.0.1:9997/userService/user") .type(MediaType.APPLICATION_XML).put(user2); //调用void delete(@PathParam("id")Integer id); Integer id1=1; WebClient.create("http://127.0.0.1:9997/userService/user/"+id1) .type(MediaType.APPLICATION_XML).delete(); //调用User findOne(@PathParam("id")Integer id); Integer id2=2; User user = WebClient.create("http://127.0.0.1:9997/userService/user/"+id2) .type(MediaType.APPLICATION_XML).get(User.class); System.out.println(user); //调用List<User> findAll(); Collection<? extends User> collection = WebClient .create("http://127.0.0.1:9997/userService/user") .accept(MediaType.APPLICATION_XML) .getCollection(User.class); System.out.println(collection); } }
4.JAX-RS 如何传输 JSON 格式的数据
如果指定客户端要获取 json 内容
错误:Caused by: javax.ws.rs.ProcessingException: No message body writer has been found
for class cn.itcast.cxf.domain.User, ContentType: application/json
解决方法:导入pom坐标
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.3.7</version> </dependency>

浙公网安备 33010602011771号