什么是WebService、使用cxf+spring来搭建Web服务

WebService  可以实现一种分布式的开发
--CXF:

Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXFApache CXF 是一个开源的 web Services 框架,CXF 帮助您构建和开发 web Services ,它支持多种协议,比如:SOAP1.1,1,2XML/HTTPRESTful 或者CORBA

RESTful: 一种风格而不是一个协议。它理念是网络上的所有事物都被抽象为资源,每个资源对应一个唯一的资源标识符。

Cxf是基于SOA总线结构,依靠spring完成模块的集成,实现SOA方式。

灵活的部署: 可以运行在Tomcat,Jboss,Jetty(内置),weblogic上面。

--Restful网络

开发WebService的要素
 1. Provider  提供者   webservice实现方,对外提供webservice的业务接口
 2. Requester 请求者   webservice调用方,或者 客户端  app  程序   网站  ssm  main()
 3. Registry  注册者

 WSDL 描述语言  就是一个XML文档
 webservice是通过xml来进行交互
 使用xml作用:与平台无关性,与语言无关性

WebService相当于一个部署在网络上的应用程序,此应用对外提供服务(业务功能)
例如,天气预告

这里详细阐述cxf在客户端和服务器的部署及使用:

1.首先在web.xml文件中配置一个中央控制器(服务端的开发本身就是基于MVC的)

<!-- CXF 中央控制器 -->
  <servlet>
  	<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>

2.如果用到spring还要添加监听器(加载spring文件)

 <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:applicationContext-*.xml</param-value>  
    </context-param>  
    <listener>  
        <listener-class>  
            org.springframework.web.context.ContextLoaderListener     
        </listener-class>  
    </listener>  

3.在创建的动态web工程中导入cxf的jar包:

4.创建服务器的pojo类(注意实现序列化接口并加版本号,因为数据要在网络上远程传输)


import java.io.Serializable;

public class Product implements Serializable {
    //版本号
	private static final long serialVersionUID = 1L;

	private String productName;
	private Double price;
	
	public Product() {
		super();
	}
	public Product(String productName, Double price) {
		super();
		this.productName = productName;
		this.price = price;
	}
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}
	public Double getPrice() {
		return price;
	}
	public void setPrice(Double price) {
		this.price = price;
	}
	@Override
	public String toString() {
		return "Product [productName=" + productName + ", price=" + price + "]";
	}
	
}

5.然后创建服务端的业务层方法:接口必须要用@WebService方法修饰

@WebService
public interface ProduceService {
    //在springcloud分布式开发中业务类就相当于一个web服务,对外就是提供业务数据的
	List<Product> findAllProduct();
}

6.接下来要在(applicationContext-*.xml)服务端配置一段代码:

	<!-- 暴露应用程序接口 -->
	<jaxws:endpoint id="productServiceImpl" 
	                implementor="com.cxf.service.ProductServiceImpl" 
	                address="/productService"></jaxws:endpoint>
	

把业务接口的实现类的全路径名拷贝到implementor中,这里spring通过id得到实例,这个实例是通过远程访问address里的地址来得到一个接口对象(实例)

这样就完成了一个web服务的发布,接下来部署到tomcat中

访问路径:localhost8080/+项目名/+web.xml文件中cxf中央控制器的url-pattern标签中的内容+/

http://localhost:8080/Day1105_WebService/services

http://localhost:8080/Day1105_WebService/services/productService?wsdl这里的productService就是服务端spring配置文件中的address中的访问地址,?wsdl就是网络服务描述语言(Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

7.接下来要在(applicationContext-*.xml)客户端配置一段代码;

启动服务端tomcat:访问http://localhost:8080/Day1105_WebService/services/productService?wsdl

在页面显示的xml文件末尾有个网站:

把这个网站地址放到客户端的spring配置文件里的address里:

<jaxws:client id="productService" 
   	address="http://localhost:8080/Day1105_WebService/services/productService"
   	serviceClass="com.cxf.service.ProduceService" />

访问服务端以后要返回一个远程回来的代理接口:即serviceClass里的类

这个代理接口就是当初我们在客户端原封不动拷贝过来的带package名的接口(实际上客户端也可以将服务端的pojo和service两个package打成jar包放到客户端项目里供其调用)

把接口的全路径名(包名加类名)原封不动拷贝到serviceClass以后就完成了第一部配置,含义是:

address就是远程访问服务器的地址,serviceClass就是远程返回的代理接口对象,id就是spring容器当中的引用(通过id引用就可以得到远程访问的代理接口对象)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

怎么用这个cxf提供的服务:

在客户端做一个测试类访问(当然也可以通过其他方式访问)以spring的方式访问代码如下(main方法也相当于一个程序)

public class CXFSpringClient {
    //以Spring方式访问
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-client.xml");
        //获取远程访问服务器返回的代理接口对象
        ProduceService service = context.getBean("productService",ProduceService.class);
        List<Product> list = service.findAllProduct();
        for(Product product : list){
            System.out.println(product);
        }
    }
}

第二种访问方式:使用JaxWsDynamicClientFactory工厂类(动态的方式)访问,用这种方式不需要配置applicationContext.xml

public class JaxWsDynamicClient {
    public static void main(String[] args) {
        try{
            JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
            //现在网络上也会提供一些免费的web服务供我们访问
            String url = "http://localhost:8080/Day1105_WebService/services/productService?wsdl";
            String methodname="findAllProduct";
            //通过工厂类创建客户端,通过invoke调用方法
            Object[] results=factory.createClient(url).invoke(methodname);
            List<Product> list =(List<Product>) results[0];
            for (Product product:list) {
                System.out.println(product);
            }
        }catch(Exception e){
            e.printStackTrace();
        }

    }

注意,此处List里面的对象是pojo中的实体类,必须将pojo中的实体类放到service包中,也就是接口和实体类在同一个包下,否则接口包中找不到动态代理对象需要的实体类就会报错。

第三种:通用性更高的动态调用,客户端甚至不需要有代理对象的接口:

服务端会定义新方法把发送给客户端的对象类型或List等其他类型转换成String再发送到客户端!

这里用到了阿里巴巴的工具包fast-json.jar需要导包


@WebService
public interface ProduceService {
	List<Product> findAllProduct();
	String getByJson();
}
--------------------------------------------------------------------------
import com.alibaba.fastjson.JSON;
@WebService
public class ProductServiceImpl implements ProduceService {

	@Override
	public List<Product> findAllProduct() {
		List<Product> list = new ArrayList<Product>();
		for (int i=0;i<3;i++) {
			list.add(new Product("ihpone",3000D));
		}
		return list;
	}

	@Override
	public String getByJson() {
		List<Product> list = new ArrayList<Product>();
		for (int i=0;i<3;i++) {
			list.add(new Product("ihpone",3000D));
		}
		String json = JSON.toJSONString(list);
		return json;
	}

}

然后发布出去(启动服务端tomcat),看wsdl里有没有新添加的json信息,有就说明发布成功

客户端创建一个测试类测试:

    //不封装,收到的是json的数据而不是自定义的封装对象
    public static void main(String[] args) {
        try{
            Object[] result = JaxWsDynamicClientFactory.newInstance() 
           .createClient("http://localhost:8080/Day1105_WebService/services/productService?wsdl")
           .invoke("getByJson");
            JSONArray array = JSON.parseArray(result[0].toString());
            for (int i=0;i<array.size();i++ ){
                JSONObject obj = array.getJSONObject(i);
                System.out.println(obj.getString("productName")+","+obj.getDouble("price"));
            }
        }catch(Exception e){

            e.printStackTrace();
        }
    }
}

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

RESTful 风格的 webservice 越来越流行了, sun 也推出了 RESTful WebService 的官方规范: JAX-RS ,全称:

Java API for RESTful WebService。该规范定义了一系列的注解

RESTful 简化了 web service 的设计,它不再需要 wsdl ,也不再需要 soap 协议,

而是通过最简单的 http 协议传输数据 ( 包括 xml 或 json) 。
既简化了设计,也减少了网络传输量(因为只传输代表数据的 xml 或 json ,没有额外的 xml 包装)。

REST(Representational State Transfer-表现层状态转化)是一种新的软件架构风格,
它以资源(resource)为核心,使用 HTTP、 URI、XML 以及 HTML 等流行协议和标准来完成对资源的操作及显示。
这些操作包括获取、创建、修改和删除资源(CRUD),分别对应于 HTTP 协议的 GET、POST、PUT 和 DELETE 方法。

RESTful架构可以总结为以下三个内容: 
(1)每一个URI代表一种资源; 
(2)客户端和服务器之间,传递这种资源的某种表现层; 
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。

对应数据库的操作, 有以下请求
GET用来获取资源,
POST用来新建资源(也可以用于更新资源),
PUT用来更新资源,
DELETE用来删除资源。

注释(Annotation):
在 javax.ws.rs.* 中定义,是 JAX-RS (JSR 311) 规范的一部分。  
@Path:定义资源基 URI。由上下文根和主机名组成,资源标识符类似于 http://localhost:8080/RESTful/rest/hello。  
@GET:这意味着以下方法可以响应 HTTP GET 方法。  
@Produces:以纯文本方式定义响应内容 MIME 类型。  

@Context: 使用该注释注入上下文对象,比如 Request、Response、UriInfo、ServletContext 等。  
@Path("{contact}"):这是 @Path 注释,与根路径 “/contacts” 结合形成子资源的 URI。  
@PathParam("contact"):该注释将参数注入方法参数的路径,在本例中就是联系人 id。其他可用的注释有 @FormParam、@QueryParam 等。  
@Produces:响应支持多个 MIME 类型。在本例和上一个示例中,APPLICATION/XML 将是默认的 MIME 类型。


http://localhost:8080/cxf-restful-server/services

猜你喜欢

转载自blog.csdn.net/sinat_41897556/article/details/83901931