Java进阶学习第三十四天(WebService)

版权声明:使用本品须Jack Gao同意,违者必究 https://blog.csdn.net/Mr_GaoYang/article/details/85099522

一、WebService介绍

1、使用场景
① 不同的移动客户端访问
② 需要访问第三方的项目

2、ISO的七层模型:物理层、数据链路层、网络层、传输层、表示层、会话层、应用层

3、基于Socket创建Web服务
Socket原理图
Scoket原理图
① Socket通信的服务端,实现大小写转化

public class SocketSer {
	public static void main(String[] args) throws Exception {
		ServerSocket ss=new ServerSocket(6666);
		boolean flag=true;
		while(flag){
			//接收客户端的请求
			System.out.println("监听客户端的数据:");
			Socket sc = ss.accept();
			InputStream is = sc.getInputStream();
			byte[] buffer=new byte[1024];
			int len=-1;
			len=is.read(buffer);
			String getData=new String(buffer, 0, len);
			System.out.println("从客户端获取的数据:"+getData);
			//业务处理 大小写转化
			String outPutData=getData.toUpperCase();
			//向客户端写数据
			OutputStream os = sc.getOutputStream();
			os.write(outPutData.getBytes("UTF-8"));
			//释放资源
			os.close();
			is.close();
			sc.close();
	}
	ss.close();
	}
}

② Socket客户端

public class SocketClient {
	public static void main(String[] args) throws Exception{
		//获取用户输入的数据
		Scanner input=new Scanner(System.in);
		System.out.println("请输入数据:");
		String inputData=input.nextLine();
		//开启一个Socket端口
		Socket sc=new Socket("127.0.0.1", 6666);
		OutputStream os=sc.getOutputStream();
		os.write(inputData.getBytes());
		//获取服务端回传的数据
		InputStream is = sc.getInputStream(); 
		byte[] buffer=new byte[1024];
		int len=-1;
		len=is.read(buffer);
		String getData=new String(buffer, 0, len);
		System.out.println("从服务端获取的数据:"+getData);
		//是否流
		is.close();
		os.close();
		sc.close();
	}
}

4、访问第三方应用的方式
① Socket访问:Socket属于传输层,它是对Tcp/ip协议的实现,包含TCP/UDP,它是所有通信协议的基础,Http协议需要Socket支持,以Socket作为基础
特点:
◇ 开启端口,该通信是长连接的通信 ,很容易被防火墙拦截,可以通过心跳机制来实现 ,开发难度大
◇ 传输的数据一般是字符串 ,可读性不强
◇ socket端口不便于推广:http:17.23.23.2:2345不如像www.jd.com
◇ 但是性能相对于其他的通信协议是最优的
② Http协议访问:属于应用层的协议,对Socket进行了封装
特点:
◇ 跨平台
◇ 传数据不够友好 : http://127.0.0.1:8888?username=lj&pwd=1234
◇ 对第三方应用提供的服务,一般就是封装好的一个网页
③ Webservice:(http + xml) = web Service

5、WebService概念
Web Service是 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、平台或内部协议是什么, 都可以相互交换数据,通俗的讲,Web Service就是一个部署在Web服务器上的一个,它向外界暴露出一个能够通过Web进行调用的API。这就是说,你能够用编程的方法通过Web来调用这个应用程序。我们把调用这个Web Service 的应用程序叫做客户端,发布这个web服务的机应用程序器称为Web Service服务器。

6、WebService技术规则
① 基于web的系统级接口规范
◇ 一个普通适用标准 :http+xml
◇ 任何网络通信的操作系统
◇ 自包含、自描述、模块化
◇ 发布、定位、通过web调用
② web service 技术和规则
◇ xml(可拓展标记语言)
◇ soap(简易对象访问协议)
◇ wsdl(web services 描述语言)
◇ uddi(通用描述、发现及整合)
③ 跨平台的可互操作性
◇ 基于xml
◇ 基于xsd(xml schema )
◇ 基于http
④ webservice 适用场景
◇ 跨防火墙的通信
◇ 异构系统间应用程序集成(jee:(EJB RMI)、php、c++、.net (com+))

7、WebService的优势
① 异构平台的互通性
理论上, Web Service 最大的优势是提供了异构平台的无缝街接技术手段。由于不同的用户使用不同的硬件平台,不同的操作平台,不同的操作系统,不同的软件,不同的协议通信,这就产生了互相通信的需求。 Web Service 使任何两个应用程序,只要能读写XML,那么就能互相通信
② 更广泛的软件复用
软件的复用技术通过组合已有模块来搭建应用程序,能大幅度提高软件的生产效率和质量。用户只要获得了描述 Web Service 的 WSDL 文件,就可以方便地生成客户端代理,并通过代理访问 Web Service
③ 成本低、可读性强、应用范围广
Web Service 可用基于 XML 的 SOAP 来表示数据和调用请求。并且通过 HTTP 协议传输 XML 格式的数据
④ 迅捷的软件发行方式
Web Service 将彻底地改变软件的发行方式。软件供应商可以把软件分解成若Web Service 模块构成的系统,直接在 Web 上发布

8、WebService专业名称
① XML:Extensible Markup Language ,扩展性标记语言,用于传输格式化的数据,是Web服务的基础。
◇ namespace-命名空间。
xmlns=“http://itcast.cn” 使用默认命名空间。
xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。
② WSDL: WebService Description Language – Web服务描述语言,调用该webservice api 的接口描述
◇ 通过XML形式说明服务在什么地方:地址。
◇ 通过XML形式说明服务提供什么样的方法 :如何调用
③ SOAP: Simple Object Access Protocol(简单对象访问协议)
SOAP作为一个基于XML语言的协议用于有网上传输数据,SOAP = 在HTTP的基础上+XML数据。SOAP是基于HTTP的。
SOAP的组成如下:
◇ Envelope – 必须的部分,以XML的根元素出现。
◇ Headers – 可选的。
◇ Body – 必须的,在body部分,包含要执行的服务器的方法和发送到服务器的数据。

二、调用第三方的WebService服务

1、体验webservice:登录http://www.webxml.com.cn

2、HttpClient工具
HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
HttpClient使用步骤如下:
① 创建 HttpClient 的实例
② 创建某种连接方法的实例,在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址
③ 配置要传输的参数和消息头信息
④ 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例
⑤ 通过response读取字符串
⑥ 释放连接,无论执行方法是否成功,都必须释放连接

3、准备客户端,调用第三方的webservice服务,让本项目有手机查号的功能
一般访问方式通过HttpClient
① Http-GET
② Http-Post
③ Soap (http+xml)

public class MobileCodeService {
	//1. get方式访问webservice
	public void get(String mobileCode ,String userID ) throws Exception{
		URL url=new URL("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode="+mobileCode+
				"&userID="+userID);
		HttpURLConnection conn=(HttpURLConnection) url.openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		if(conn.getResponseCode()==HttpURLConnection.HTTP_OK){ //结果码=200
			InputStream is=conn.getInputStream();
			//内存流 ,  
			ByteArrayOutputStream boas=new ByteArrayOutputStream();
			byte[] buffer=new byte[1024];
			int len=-1;
			while((len=is.read(buffer))!=-1){
				boas.write(buffer, 0, len);
			}
		    System.out.println("GET请求获取的数据:"+boas.toString());	
		    boas.close();
		    is.close();
		}
	}
	
	//2.Post请求 :通过Http-Client 框架来模拟实现 Http请求
	public void post(String mobileCode ,String userID) throws Exception{
		/**HttpClient访问网络的实现步骤:
		 *  1. 准备一个请求客户端:浏览器 
		 *  2. 准备请求方式: GET 、POST
		 *  3. 设置要传递的参数
		 *  4. 执行请求
		 *  5. 获取结果
		 */
		HttpClient client=new HttpClient();
		PostMethod postMethod=new PostMethod("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo");
		//3.设置请求参数
		postMethod.setParameter("mobileCode", mobileCode);
		postMethod.setParameter("userID", userID);
		//4.执行请求,结果码
		int code=client.executeMethod(postMethod);
		//5. 获取结果
		String result=postMethod.getResponseBodyAsString();
		System.out.println("Post请求的结果:"+result);
	}
	
	//3.soap
	public void soap() throws Exception{
		HttpClient client=new HttpClient();
		PostMethod postMethod=new PostMethod("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");
		//3.设置请求参数
		postMethod.setRequestBody(new FileInputStream("c:/soap.xml")); 
		//修改请求的头部
		postMethod.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
		//4.执行请求 ,结果码
		int code=client.executeMethod(postMethod);
		System.out.println("结果码:"+code);
		//5. 获取结果
		String result=postMethod.getResponseBodyAsString();
		System.out.println("Post请求的结果:"+result);
	}

        //Java方式访问WebService
	public static void main(String[] args) throws Exception{
		MobileCodeService ws=new MobileCodeService();
		ws.get("15626217879", "");
		ws.post("15626217879", "");
//		ws.soap();
	}
}

webservice 纳入w3c规范,其他的平台都支持该规范,都支持wsimport 方式 (对远程的webservice生成本地代理,再通过本地代理来访问webservice)
① wsimport 命令的位置: C:\Program Files\Java\jdk1.7.0_04\bin
② 要求:
jdk的版本要在 jdk 1.6.21及以上,操作系统安装的jdk版本与MyEclispe及默认指定的版本要一致
③ wsimport使用: 记得设置jdk\bin 环境变量 指定path
④ 语法:wsimport [opations] <wsdl_uri>

- wsdl_uri:wsdl 的统一资源标识符
- d  :指定要输出的文件的位置
- s  :表示要解析java的源码 ,默认解析出的是class字节码 
- p  : 指定输出的包名

通过wsimport生成本地代理来访问 webservice服务端

	public static void main(String[] args) {
		//生成服务对象
		MobileCodeWS ws=new MobileCodeWS();
		//取得webservice服务的访问方式: Soap1.1、Soap 1.2、Http-get、http-Post
		MobileCodeWSSoap mobileCodeWSSoap = ws.getMobileCodeWSSoap();
		/**
		 *  返回的数据有两种类型 : 
		 *  1. 简单的数据类型,基本数据类型:整数、布尔、字符串等
		 *  2. 复合的数据类型:结构体、数组、对象 
		 */
		//1.简单的数据
		String result=mobileCodeWSSoap.getMobileCodeInfo("13660559129", "");
		System.out.println("返回的结果:"+result);
		//2. 复合的数据  List<String> List<Student>
		ArrayOfString databaseInfo = mobileCodeWSSoap.getDatabaseInfo();
		List<String> results=databaseInfo.getString();
		//遍历集合
		for(String temp:results){
			System.out.println(temp);
		}
		//jsp  Select 
	}
}

4、自定义及发布一个webservice服务
① 声明某个业务服务为webservice服务:通过@webservice注解来声明
② 发布webservice服务:Endpoint.publish()发布

public class Phone {
	private String name;//操作系统名
	private String owner;//拥有者 
	private int total;//市场占有率
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getOwner() {
		return owner;
	}
	public void setOwner(String owner) {
		this.owner = owner;
	}
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}
}
/**手机的业务类,该业务类通过webservice对外提供服务
 * 1. 声明: @webservice
 * 2. 发布: EndPoint
 */
@WebService (serviceName="PhoneManager",//修改服务名
   targetNamespace="http://dd.ws.it.cn") //修改命名空间
//声明该业务类对外提供webservice服务,默认只是对public修饰的方法对外以webservice形式发布
public class PhoneService {
	/**@WebMethod(operationName="getMObileInfo"): 修改方法名
	 * @WebResult(name="phone"):修改返回参数名
	 * @WebParam(name="osName"):修改输入参数名
	 */
	@WebMethod(operationName="getMObileInfo")
	public @WebResult(name="phone") Phone getPhoneInfo(@WebParam(name="osName")String osName){
		Phone phone=new Phone();
		if(osName.endsWith("android")){
			phone.setName("android");phone.setOwner("google");phone.setTotal(80);
		}else if(osName.endsWith("ios")){
			phone.setName("ios");phone.setOwner("apple");phone.setTotal(15);
		}else{
			phone.setName("windows phone");phone.setOwner("microsoft");phone.setTotal(5);
		}
		return phone;
	}

	@WebMethod(exclude=true)//把该方法排除在外
	public void sayHello(String city){
		System.out.println("你好:"+city);
	}
	private void sayLuck(String city){
		System.out.println("好友:"+city);
	}
	void sayGoodBye(String city){
		System.out.println("拜拜:"+city);
	}
	protected void saySayalala(String city){
		 System.out.println("再见!"+city);
	 }
	
	public static void main(String[] args) {
		String address1="http://192.168.114.10:8888/ws/phoneService";
		// String address2="http://127.0.0.1:8888/ws/phoneManager";
		/**
		 * 发布webservice服务
		 * 1.address:服务的地址
		 * 2.implementor:服务的实现对象
		 */
		Endpoint.publish(address1, new PhoneService());
		// Endpoint.publish(address2, new PhoneService());
		System.out.println("wsdl地址 :"+address1+"?WSDL");
	}
}

③ 通过wsimport生成本地代理来访问自己发布的webservice:wsimport

public class _Main {
	public static void main(String[] args) {
		//服务
		PhoneServiceService ws=new PhoneServiceService();
		//访问方式 
		PhoneService phoneServicePort = ws.getPhoneServicePort();
		Phone phoneInfo = phoneServicePort.getPhoneInfo("android");
		System.out.println(phoneInfo.getName());
		System.out.println(phoneInfo.getOwner());
		System.out.println(phoneInfo.getTotal());
	}
}

5、需求:
① 想改方法的输入参数名、返回参数名
② 想改服务名,方法名
③ 对该业务类的某些方法不想对外发布
默认只有public 修饰的方法会以webservice的形式对外发布,而 private 受保护的、缺省的,都不会发布;我想让某些public 方法也不对外发布
解决方法:通过注解配置修改wsdl文件, 让它具有更好的可读性

6、调用教师机的ws服务步骤:
① 系统jdk环境与myeclipse jdk 环境一致:1.6.021以上
② 服务端的WDSL路径http://192.168.114.10:8888/ws/phoneService?WSDL
③ 命令行 wsimport -s ./ -p cn.itcast.ws.d http://192.168.114.10:8888/ws/phoneService?WSDL
④ 导入通过wsimport 解析的java类,再编写一个main测试

7、WSDL文件介绍 :webservice服务说明
① WSDL 文档的组成部分

元素 定义
<portType> web service 执行的操作
<message> web service 使用的消息
<types> web service 使用的数据类型
<binding> web service 使用的通信协议

② WSDL 文档的主要结构

<definitions>
<types>
	definition of types........
</types>
<message>
	definition of a message....
</message>
<portType>
	definition of a port.......
</portType>
<binding>
	definition of a binding....
</binding>
</definitions>

③ WSDL元素介绍
定义一个功能,在Java中叫做方法,在C中叫做函数;在Java中叫类,在C语言中叫做结构体。这些名词都不一样。WSDL规范为了不会产生歧义,就定义了一些新的名词来表述功能与服务。
<portType>(WSDL端口)
<portType> 元素是最重要的 WSDL 元素。 它可描述一个 web service、可被执行的操作,以及相关的消息。 可以把 元素比作传统编程语言中的一个函数库(或一个模块、或一个类)。
<operation>子元素:
对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。
<message> (WSDL消息)
<message> 元素定义一个操作的数据元素。 每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个函数调用的参数。
通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。
<types>(WSDL types)
<types> 元素定义 web service 使用的数据类型。 为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。
<binding> (WSDL Bindings)
<binding> 元素为每个端口定义消息格式和协议细节。

<message name="getTermRequest">
   <part name="term" type="xs:string"/>
</message>

<message name="getTermResponse">
   <part name="value" type="xs:string"/>
</message>

<portType name="glossaryTerms">
  <operation name="getTerm">
        <input message="getTermRequest"/>
        <output message="getTermResponse"/>
  </operation>
</portType>

8、四个概念
① soap:简单对象访问协议,包含http+xml
② Soa:面向服务的架构,它是一种思想,IBM大力提倡服务都是面向web的 ,而且是即插即用的,它有两部分组成:
◇ 面向web的服务或者是面向web的组件:WebServic(就像硬盘、cpu、内存条)
◇ 企业服务总线:EnterPrise Service Bus ,ESB(就像主板)
③ wsdl:webservice 描述语言
④ uddi:Universal Description, Discovery and Integration
统一描述、发现、集成,它是目录服务,通过该服务可以注册和发布webservcie,以便第三方的调用者统一调用

9、两个思考
① 思考:webservice在web应用的三层架构中,位于哪一层中呢?
属于业务层,即Service层
② 思考:你觉得webservice有严格的客户端和服务端吗?
没有,相对服务端和客户端

三、带有接口的webservice发布方式

1、通过EndPoint发布带有接口的webservice

/*
* 面向接口的webservice发布方式
 */
@WebService
public interface JobService {
	public String getJob();
}
@WebService(endpointInterface="cn.it.ws.e.JobService")//设置服务端点接口,指定对外提供服务的接口
public class JobServiceImpl implements JobService {
	@Override
	public String getJob() {
		return "JEE研发|Android研发|数据库|前端|测试|运维";
	}
    public void say(){
    	System.out.println("早上好!");
    }
}
public class Test {
	public static void main(String[] args) {
		JobService jobService=new JobServiceImpl();
		String address="http://192.168.114.10:9999/ws/jobservice";
		Endpoint.publish(address, jobService);
		System.out.println("wsdl地址:"+address+"?WSDL");
	}
}

2、 wsimport http://192.168.114.10:99998/ws/jobService?WSDL

3、打jar包
命令行: jar -cvf jobService.jar ./cn

public class Test {
	/*
	* 测试通过实现接口的webservice发布方式
	 */
public static void main(String[] args) {
	JobServiceImplService ws=new JobServiceImplService();
	JobService jobServiceImplPort = ws.getJobServiceImplPort();
	String jobs = jobServiceImplPort.getJob();
	//"JEE研发工程师|Android研发工程师|数据库工程师|前端工程师|测试工程师|运维工程师"
	String[] jobArray=jobs.split("\\|");
	System.out.println(jobArray[2]);
	System.out.println(jobArray[0]);
	System.out.println(jobArray[3]);
    }
}

四、远程访问天气预报服务(jsp+ajax+servlet+webservice)

1、webservice 客户端访问的方式
① java代码来访问
② ajax 方式异步加载webservice

2、通过 ajax 异步加载天气信息实现步骤:
① 了解远程第三方的天气预报webservice服务
② wsimport 生成本地代理
③ 准备一个index.jsp页面,显示城市信息,下拉城市显示天气信息

<html>
  <head>
  <script type="text/javascript" src="jquery-1.8.2.js"></script>
  </head>
  
  <body>
   <select id="province">
   <option value="31124">广东省</option>
   </select>
   <select id="city">
   <option value="2350">广州</option>
   <option value="2419">深圳</option>
   <option value="2351">东莞</option>
   </select>
   <hr/>
   <span>XXXX</span>
   <script type="text/javascript">
     $("#city").change(function(){
       var city=$("#city option:selected").val();
       $.post("weatherServlet",{"city":city},function(backdata){
         $("span").text(backdata).css("color","blue");
       });
     });
   </script>
  </body>
</html>

④ 准备一个weatherServlet,通过它来访问webservcie

public class WeatherServlet extends HttpServlet {
	private WeatherWS ws;
	public WeatherServlet() {
		super();
	}
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String cityCode=request.getParameter("city");
		System.out.println("获取城市的id"+cityCode);
		//通过webservice获取远程的天气预报信息
		WeatherWSSoap weatherWSSoap = ws.getWeatherWSSoap();
		List<String> weathers = weatherWSSoap.getWeather(cityCode, "").getString();
		String weather=weathers.get(8);//取得温度信息
		//把结果回显给页面
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter printWriter=response.getWriter();
		printWriter.write(weather);
		printWriter.flush();
		printWriter.close();	
	}

	public void init() throws ServletException {
		// Put your code here
		ws=new WeatherWS();
	}
}

⑤ Servlet要在web.xml注册

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>WeatherServlet</servlet-name>
    <servlet-class>cn.it.ws.weather.WeatherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>WeatherServlet</servlet-name>
    <url-pattern>/weatherServlet</url-pattern>
  </servlet-mapping>

</web-app>

五、CXF框架

1、为了解决上述方法通过Jdk实现webservice的不足: 希望tomcat启动时,webservice服务能够开启 ,最好与Spring集成;希望有一个webservice的服务列表 ,通过Webservice框架来实现(axis2、xfire……),可以使用CXF框架,发布webservice服务,并使用客户端远程访问webservice

2、CXF介绍(soa的框架)
① cxf 是 Celtrix (ESB框架)和 XFire(webserivice) 合并而成,并且捐给了apache
② CxF的核心是org.apache.cxf.Bus(总线),类似于Spring的 ApplicationContext
③ CXF默认是依赖于Spring的
④ Apache CXF 发行包中的jar,如果全部放到lib中,需要 JDK1.6 及以上,否则会报JAX-WS版本不一致的问题
⑤ CXF 内置了Jetty服务器 ,它是servlet容器,好比tomcat

3、CXF特点
① 与Spring、Servlet做了无缝对接,cxf框架里面集成了Servlet容器Jetty
② 支持注解的方式来发布webservice
③ 能够显示一个webservice的服务列表
④ 能够添加拦截器:输入拦截器、输出拦截器(输入日志信息拦截器、输出日志拦截器、用户权限认证的拦截器)

4、需求:开发语言排行描述服务
① 服务器端

@WebService(serviceName="languageManager")
public interface LanguageService {
	public @WebResult(name="language")String getLanguage(@WebParam(name="position")int position);
}
public class LanguageServiceImpl implements LanguageService {
	/* (non-Javadoc)
	 * @see cn.it.ws.cxf.a.LanguageService#getLanguage(int)
	 */
	@Override
	public String getLanguage(int position){
		String language=null;
		switch (position) {
		case 1:
			language="java"; 
			break;
		case 2:
			language="C";
			break;
		case 3:
			language="Objective-C";
			break;  
		case 4:
			language="C#";
			break;
		default:
			break;
		}
		return language;
	}
	/*
	*   通过cxf框架发布webservice
	 *  1、ServerFactoryBean
	 *    - 不设置注解也可以发布webservice服务,不支持注解
	 *    - 不支持拦截器的添加
	 *  2、JaxWsServerFactoryBean
	 *    - 支持注解
	 *    - 可以添加拦截器
	 *  3、webservice 访问流程:
	 *    - 检测本地代理描述的wsdl是否与服务端的wsdl一致,俗称为握手
	 *    - 通过soap协议实现通信,采用的是post请求,数据封装在满足soap规约的xml中
	 *    - 返回数据 同样采用的是soap通信,数据封装在满足soap规约的xml中
	 * @param args
	
	public static void main(String[] args) {
		LanguageService languageService=new LanguageServiceImpl();
		ServerFactoryBean bean=new ServerFactoryBean();
		//Endpoint :地址,实现对象
		bean.setAddress("http://192.168.114.10:9999/ws/cxf/languangeService");
		bean.setServiceClass(LanguageService.class);//对外提供webservcie的业务类或者接口
		bean.setServiceBean(languageService);//服务的实现bean
		bean.create();//创建,发布webservice
		System.out.println("wsdl地址:http://192.168.114.10:9999/ws/cxf/languangeService?WSDL");
	}
	 */
	 
	public static void main(String[] args) {
		LanguageService languageService=new LanguageServiceImpl();
		JaxWsServerFactoryBean bean=new JaxWsServerFactoryBean();
		//Endpoint :地址  , 实现对象
		bean.setAddress("http://192.168.114.10:9999/ws/cxf/languangeService");
		bean.setServiceClass(LanguageService.class);//对外提供webservcie的业务类或者接口
		bean.setServiceBean(languageService);//服务的实现bean
		//添加输入拦截器:输入显示日志信息的拦截器
		bean.getInInterceptors().add(new LoggingInInterceptor());
		//添加输出拦截器:输出显示日志信息的拦截器
		bean.getOutInterceptors().add(new LoggingOutInterceptor());
		bean.create();//创建,发布webservice
		System.out.println("wsdl地址:http://192.168.114.10:9999/ws/cxf/languangeService?WSDL");
	}
}

② 客户端

public class Test {
  /*
  * 测试有CXF框架发布的webservice服务
   */
	public static void main(String[] args) {
		LanguageManager ws=new LanguageManager();
		LanguageService languageServicePort = ws.getLanguageServicePort();
		System.out.println(languageServicePort.getLanguage(1));
	}
}

5、Spring+CXF整合来管理webservice实现步骤
前面的服务发布包括创建服务类都是硬编码的方式,是否可以使用配置的方式来发布服务类呢?答案是肯定的,这就要同Spring集成了。由于cxf的项目已经集成了Spring(自带了Spring lib),所以CXF的服务都是在Spring的配置文件中完成的,并且我们需要把项目发布到tomcat中
① 添加cxf.jar 包(集成了Spring.jar、servlet.jar )、spring.jar包、servlet.jar 包
【添加Spring.jar:右击项目>Myeclipse>Project Facets[Capablilities]>Install Spring Facet】
② 编写业务类,通过CXF来发布webservice

public class Employee {
	private Integer  id;
	private String name;
	private Integer age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}
@WebService(serviceName="EmployeeService")
public interface EmployeeManager {
	public abstract void add(@WebParam(name="employee")Employee employee);
	public abstract @WebResult(name="employees")List<Employee> query();
}
/*
* 员工管理的业务实现类
 */
public class EmployeeManagerImpl implements EmployeeManager {
	private List<Employee> employees=new ArrayList<>();
	@Override
	public void add(Employee employee){
		//添加到集合中
		employees.add(employee);
	}
	@Override
	public List<Employee> query(){
		return employees;
	}
}

③ 添加一个CXF请求的 Servlet,用来处理webservice的请求 ,过滤的地址:/ws/*
④ 配置Spring的配置文件:applicationContext.xml ,把cxf的bean在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:p="http://www.springframework.org/schema/p"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	  http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

<bean id="employeeManagerImpl" class="cn.it.ws.cxf.b.EmployeeManagerImpl"></bean>
<!-- 配置cxf   
     地址:   http://192.168.114.10:8080/CXF_Server/ws/employeeManager
     组成 :  http://192.168.114.10:8080 +CXF_Server( 项目名)+ws(过滤的路径)+/employeeManager(自定义部分)
     服务类 :
     服务的实现类:
     拦截器  
-->
<jaxws:server address="/employeeManager" serviceClass="cn.it.ws.cxf.b.EmployeeManager">
	<jaxws:serviceBean>
		<ref bean="employeeManagerImpl"/>
	</jaxws:serviceBean>
	<!-- 配置输入显示日志信息的拦截器   -->
	<jaxws:inInterceptors>
		<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
	</jaxws:inInterceptors>
	<jaxws:outInterceptors>
		<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
	</jaxws:outInterceptors>
</jaxws:server>
</beans>

⑤ 在web.xml中配置 CXF的Servlet,添加spring的监听

<?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_3_0.xsd" version="3.0">
  <display-name>CXF_Server</display-name>
  <!-- 添加  CXF 的Servlet ,处理 webservice的请求 -->
  <servlet>
  <servlet-name>cxf</servlet-name>
  <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
  <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
   <servlet-name>cxf</servlet-name>
   <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>
  <!-- Spring 监听添加 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
</web-app>

⑥ 通过wsimport生成本地代理,访问webservice

6、webservice测试工具
Launch SOAP Web Services Exprlorer>WSDL Page>WSDL Main>输入地址

猜你喜欢

转载自blog.csdn.net/Mr_GaoYang/article/details/85099522