Bootstrap

CXF WebService开发

很多个系统,进行分布的部署,分布的系统数据通信 解决技术就是 WebService。
CXF 是目前最主流 WebService 开发框架

CXF主要分为两种服务

JAX-WS 传输数据,就是 XML 格式,基于 SOAP 协议
JAX-RS 传输数据,传输 XML 格式或者 JSON 格式,基于 HTTP 协议

JAX-WS独立服务使用

导入CXFjar包支持 Maven坐标

   	<dependencies>
		<!-- 进行jaxes 服务开发 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>3.0.1</version>
		</dependency>
	<!-- 内置jetty web服务器 -->
		<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>
	</dependencies>

编写服务端的代码

  1. 实体类
    Car

    private Integer id;
    private String carName;
    private Double price;
    

    User

    private Integer id;
    private String carName;
    private Double price;
    
  2. 服务端程序
    IUserService接口

    @WebService
    //用来标记类是WebService服务提供对象
    public interface IUserService {
    @WebMethod
    //用来标记方法是WebService提供的方法
    public String sayHello(String name);
    
    @WebMethod
    public List<Car> findCarsByUser(User user);
    }
    

    UserServiceImpl

    @WebService(endpointInterface = "cn.lzh.cxf.service.IUserService", serviceName = 		"userService")
    //endpointInterface接口服务完整全类名
    //serviceName服务名称
    public class UserServiceImpl implements IUserService {
    //简单参数传递
    public String sayHello(String name) {
    	return "Hello," + name;
    }
    
    //复杂参数 传递
    public List<Car> findCarsByUser(User user) {
    	// 这里本应该查询数据库的,为了演示,做一些假数据
    	if ("xiaoming".equals(user.getUsername())) {
    		List<Car> cars = new ArrayList<Car>();
    		Car car1 = new Car();
    		car1.setId(1);
    		car1.setCarName("大众途观");
    		car1.setPrice(200000d);
    		cars.add(car1);
    
    		Car car2 = new Car();
    		car2.setId(2);
    		car2.setCarName("现代ix35");
    		car2.setPrice(170000d);
    		cars.add(car2);
    
    		return cars;
    	} else {
    		return null;
    	}
    }
    }
    
  3. 将userService注册到网上

    //将CXY 将 UserServer注册到网络上
    	//1.服务实现对象
    	IUserService userService = new UserServiceImpl();
    	//2发布服务地址
    	String address = "http://localhost:8888/userService";
    	//3发布服务
    	Endpoint.publish(address, userService);
    	System.out.println("服务已经启动...");
    

    成功界面
    在这里插入图片描述

  4. 客户端

    //ws客户端
    public class WS_Client {
    
    public static void main(String[] args) {
    	//编写客户端 调用发布WebService服务
    	JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
    	
    	jaxWsProxyFactoryBean.setServiceClass(IUserService.class);
    	jaxWsProxyFactoryBean.setAddress("http://localhost:9999/userService");
    	
    	//调用远程服务代理对象
    	IUserService proxy = (IUserService) jaxWsProxyFactoryBean.create();
    	//调用代理对象任何一个方法,都将网络调用web服务
    	System.out.println(proxy.sayHello("你好"));
    }
    }
    

    在这里插入图片描述
    服务启动成功 可以用网络调用该服务
    注意
    可以通过
    jaxWsProxyFactoryBean.getInInterceptors().add(new LoggingInInterceptor());
    jaxWsProxyFactoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
    开启日志信息

JAX-WS和Spring整合开发WebService

导入CXF_WS的Maven坐标 与tomcat插件

<dependencies>
  <!-- CSF WS开发核心 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>3.0.1</version>
		</dependency>
	
		<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>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>tomcat-maven-plugin</artifactId>
				<version>1.1</version>
				<configuration>
					<port>9800</port>
				</configuration>
			</plugin>
		</plugins>
	</build>

配置web.xml

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- spring核心监听器 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- CXF WS基于web访问的servlet -->
	<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>

application的配置

	<?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.xsd
	http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
	<!-- 
		address 客户端访问服务器路径
		serviceClass 配置接口
		serviceBean 配置实现
	 -->
	<jaxws:server id="userService" address="/userService" serviceClass="cn.lzh.cxf.service.IUserService">
		<jaxws:serviceBean>
			<bean class="cn.lzh.cxf.service.UserServiceImpl" />
		</jaxws:serviceBean>
	</jaxws:server>
	
</beans>

客户端的测试
application-test的配置

<?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.xsd
	http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<!--
	 serviceClass :服务接口
	 address 服务访问地址
	 -->
	<jaxws:client id="userServiceClient" serviceClass="cn.lzh.cxf.service.IUserService" 
		address="http://localhost:9800/cxf_ws_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>

测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
public class WS_spring_test {
	
	@Autowired
	private IUserService proxy;
	
	@Test
	public void testCXF(){
		System.out.println(proxy.sayHello("你好"));
	}

}

结果:
在这里插入图片描述
服务访问成功

JAX-RS独立使用

重点
要先了解restful风格:
在我认为restful是通过资源进行定位或进行操作的,不是什么标准,也不是什么协议,互联网的任何事物都是

资源,比如说网络上有张图片,我只需要知道那张图片的名字,通过图片名字的url来定位到这张图片,
资源操作 我们用数据库的crud 对应htpp方法,比如put修改 post保存 get查询,delete删除,这样我们能创建

统一的接口,减少代码的开发,提升开发效率 而且基于http协议,支持多种消息格式,比如xml jason 更容

易实现缓存机制,tomcat有缓存机制,第一次访问资源,第二次访问资源,返回304客户端调用本地

  1. 添加Maven依赖
<dependencies>
  <!-- 使用CXF RS开发 -->
  	<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>3.0.1</version>
		</dependency>
 <!-- 内置jetty web服务器 -->
		<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>
  </dependencies>
  1. 编写实体类
    car
	@XmlRootElement(name = "Car")
	//指定序列化时(转换xml json)对象名字
public class Car {
	private Integer id;
	private String carName;
	private Double price;

	public Integer getId() {
		return id;
	}

注意要写@XMLRootElement注解
User

	@XmlRootElement(name = "User")
public class User {
	private Integer id;
	private String username;
	private String city;

	private List<Car> cars = new ArrayList<Car>();

  1. 编写服务端程序
    IUserService
	@Path("/userService")
//服务访问资源路径
@Produces("*/*")
//生成(返回值) 指定能够生成哪种格式数据返回给客户端
public interface IUserService {

	@POST
	//请求http协议的 增加
	@Path("/user")
	@Consumes({ "application/xml", "application/json" })
	//方法的参数 指定能够处理客户端传递过来的数据格式
	public void saveUser(User user);

	@PUT
	@Path("/user")
	//请求http协议的 修改
	@Consumes({ "application/xml", "application/json" })
	public void updateUser(User user);

	@GET
	@Path("/user")
	//请求http协议的 查询
	@Produces({ "application/xml", "application/json" })
	
	public List<User> findAllUsers();
	//生成(返回值) 指定能够生成哪种格式数据返回给客户端
	@GET
	@Path("/user/{id}")
	@Consumes("application/xml")
	@Produces({ "application/xml", "application/json" })
	public User finUserById(@PathParam("id") Integer id);

	@DELETE
	@Path("/user/{id}")
	//请求http协议的 删除
	@Consumes("application/xml")
	public void deleteUser(@PathParam("id") Integer id);
}

注意 如果要返回数据要加@Produces注解 参数为可以处理的数据格式
注意 如果要接受参数要加@Consumes注解 参数为可以处理的数据格式

将服务发布到网络

	//创建业务接口实现类对象
		IUserService userService = new UserServiceImpl();
		//服务器FactoryBean创建服务
		JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
		//将那些实体转换成xml、json发送
		restServer.setResourceClasses(User.class,Car.class);
		//设置服务的bean
		restServer.setServiceBean(userService);
		//设置地址
		restServer.setAddress("http://localhost:9999");
		
		//打印日志
		restServer.getInInterceptors().add(new LoggingInInterceptor());
		restServer.getOutInterceptors().add(new LoggingOutInterceptor());
		//发布服务
		restServer.create();

客户端代码

首先要在maven添加WebClient依赖

<!-- 使用rs客户端 里面有个工具包为rs client -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-client</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>
public static void main(String[] args) {
		//create 建立与调用服务资源路径链接
		//type 发送给服务器数据格式--@Consume
		//accept接受服务器传输数据格式--@Produces
		Collection<? extends User> collection = WebClient.create("http://localhost:9999/userService/user").accept(MediaType.APPLICATION_XML).getCollection(User.class);
		System.out.println(collection);
		//添加用户
		User user = new User();
		WebClient.create("http://localhost:9999/userService/user").type(MediaType.APPLICATION_XML).post(user);
	}

成功:
在这里插入图片描述
注意
put为修改 post为添加 delete为删除 get为查找

传输json
错误:Caused by: javax.ws.rs.ProcessingException: No message body writer has been found
for class cn.itcast.cxf.domain.User, ContentType: application/json

解决:添加json转换器

<!-- 在CXF扩展原提供者,提供转换JSON接口 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-extension-providers</artifactId>
			<version>3.0.1</version>
		</dependency>
		<!-- CXF默认的扩展提供者 -->
		<dependency>
			<groupId>org.codehaus.jettison</groupId>
			<artifactId>jettison</artifactId>
			<version>1.3.7</version>
		</dependency>

JAX-RS 整合Spring

导入Maven坐标

	<dependencies>
  		<!-- CXF_rs开发必须要的jar -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>3.0.1</version>
		</dependency>
		<!-- 日志包 -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>
		<!-- 客户端程序坐标 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-client</artifactId>
			<version>3.0.1</version>
		</dependency>
		<!-- 扩展json提供者 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-extension-providers</artifactId>
			<version>3.0.1</version>
		</dependency>
		<!-- 转换json包依赖 -->
		<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>
		<!-- springweb包 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<!-- spring -juite -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<!-- junit的依赖包 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>

	</dependencies>
	<!-- tomcat插件 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>tomcat-maven-plugin</artifactId>
				<version>1.1</version>
				<configuration>
					<port>9800</port>
				</configuration>
			</plugin>
		</plugins>
	</build>

web.xml配置

<!-- spring配置文件位置 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- spring核心监听器 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- CXF service的Servlet -->
	<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>

applicationContext.xml配置

<!-- 
		address 发布服务地址
		servicesBeaan 服务实现类
	 -->
	<jaxrs:server id="userService" address="/userService" >
		<jaxrs:serviceBeans>
			<bean class="cn.lzh.cxf.service.UserServiceImpl" />
		</jaxrs:serviceBeans>
		<jaxrs:inInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
		</jaxrs:inInterceptors>
		<jaxrs:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
		</jaxrs:outInterceptors>
	</jaxrs:server>

注意
最终访问资源服务路径
服务器根目录地址+web.xml配置+applicationContext.xml address配置,类 @Path+方法@Path

;