wsdl说明文档

xsd ---->定义了schema标签的namespace
wsdl ---->定义了wsdl标签的namespace


    
        
            
        
    
    
    
    
    
    
    
    
    
        
        
    









课程安排:
    web service 2
    ibatis (mybatis) 1

复习2个相关的重要知识
    a schema约束
        1. namespace : schema文件的标识属性,相当于id,每个schema文件需要有一个唯一的namespace值
        2. targetNameSpace :指定当前schema文件的namespace值
        3. xmlns :引入一个schema约束,它的值为一个schema的namespace值
        4. element :定义标签
    b. Http协议
        1. 请求的组成:
            请求行,请求头,请求体(Post)
            client--》server
        2. 响应的组成
            状态行,响应头,响应体
            server-->client
        3. 请求的过程
        
webservice
    http+xml(schema)
    
Web service是什么?
    web服务:服务器端整出一些资源可以让客户端应用访问(获取数据)
    一个跨语言、跨平台的规范(抽象)
    多个跨平台、跨语言的应用间通信整合的方案(实际)
    
为什么要用Web service?
    业务需求:
        应用A: java写的,运行在windows平台下
            List getAllUsers();
        应用B: c语言写的,运行在linux平台下
            需要请求应用A的getAllUsers()得到所有的user信息来展示
    web service能解决:
        跨平台调用 
        跨语言调用
        远程调用
        
什么时候使用web Service?
    同一家公司的新旧应用
    不同公司的应用间
        分析业务需求:淘宝网与顺风物流系统如何交互?
    一些提供数据的内容聚合应用:天气预报、股票行情
    
如何做web service的开发?
    服务器端(处理客户端应用的请求,执行业务逻辑,提供数据)
    客户端(发送请求,获取数据)
    
几个常用的
    WSDL:web service definition language
        对应一种类型的文件.wsdl
        一个web service对应一个唯一的wsdl文档
        定义了web service的服务器端与客户端应用交互传递请求和响应数据的格式和方式
    SOAP:simple object access protocal
        http+xml片断
        soap消息:请求消息和响应消息
        它依赖于wsdl文档的定义
    SEI:Service EndPoint Interface
        web service的终端接口,就是服务器端用来处理请求的接口(其中的方法就是处理请求的方法)
    CXF:Celtix and XFire
        一个apache的webservice框架
    
开发web service
    1. 使用JDK开发
①. 服务器端
    编码:
        a. 创建一个基于jdk6以上版本的java工程
        b. 定义SEI web service Endpoint interface(web service终端接口)
            @WebService
            public interface HelloWS {
                @WebMethod
                public String sayHello(String name);
            }
        c. 定义SEI的实现类:
            @WebService
            public class HelloWSImpl implements HelloWS {
                @Override
                public String sayHello(String name) {
                    System.out.println("sayHello "+name);
                    return "hello "+name;
                }
            }

    发布:
        public class Server {
            public static void main(String[] args) {
                //客户端发送web service请求的url
                String address = "http://192.168.1.104/ws_server/helloWS";
                //处理请求的SEI对象
                HelloWS helloWS = new HelloWSImpl();
                //发布web service
                Endpoint.publish(address, helloWS);
                System.out.println("发布web service成功!");
            }
        }
②. 客户端
    1. eclipse Web Service浏览器
        a. 查看Web Service所对应的WSDL文档:...?wsdl
        b. 使用eclipse访问
            请求体:SOAP Request Envelope
                
                    
                        
                            tt
                        
                    
                
            响应体:SOAP Response Envelope
                
                    
                        
                            hello tt 
                        
                    
                 
    2. 编码实现
        a. 创建客户端java应用
        b. 在应用的src下执行cxf的命令生成客户端代码:
            wsimport -keep http://192.168.1.104/ws_server/helloWS?wsdl
        c. 编写客户端调用的测试代码,执行:
            public class Client {
                public static void main(String[] args) {
                    //创建SEI的工厂对象
                    HelloWSImplService factory = new HelloWSImplService();
                    //得到一个SEI实现类对象
                    HelloWSImpl helloWS = factory.getHelloWSImplPort();
                    //调用SEI的方法,此时才去发送web Service请求,并得到返回结果
                    String result = helloWS.sayHello("Tom");
                    System.out.println(result);
                }
            }
                    
        ③.请求过程记录:使用eclipse的tcp/ip工具进行请求的监控
1. 配置tcp/ip监视器(请求转发+请求信息记录)
    监听port : 80(wsdl文件中的address属性一致)
    监听主机 :ip
    转发的port : 8989(server端一致)
2. 将webservice的wsdl文件保存到client应用中: helloWS.wsdl
3. 修改helloWS.wsdl文件中的uri : port adresss属性 8989-->80
4. 在client应用的src下执行命令: wsimport -keep 本地wsdl文件---》生成client端代码
5. 借助生成的代码请求web service
            
④.应用:编写天气预报web service的客户端(根据城市名称得到城市今天的天气信息)
    1. 找到对应的wsdl文件所在的网络地址:http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
    2. 通过eclipse的web service浏览请求,测试是否可用
    3. 将wsdl文档保存到本地:ws_weath应用文件夹下weath.wsdl
        (将 替换成 )
    4. ws_weath应用下执行命令:wsimport -keep weath.wsdl的路径  ---》生成对应的客户端代码
    5. 编写测试程序:
    public static void main(String[] args) {
        WeatherWebService factory = new WeatherWebService();
        WeatherWebServiceSoap webServiceSoap = factory.getWeatherWebServiceSoap();
        ArrayOfString arrayOfString = webServiceSoap.getWeatherbyCityName("荆州");
        List list = arrayOfString.getString();
        for(String s : list) {
            System.out.println(s);
        }
    }

    2. 使用CXF框架开发
    
        ①.CXF : xfire-->xfire + celtrix
            做web service开发的开源框架
            
        ②.开发Server端:
            加入cxf的Jar包即可,其它不需要动
            
        ③.wsdl文件分析 :
            
            
            
                
                
                    
                        
                        
                        
                        
                        
                            
                                
                            
                        
                        
                            
                                
                            
                        
                    
                
                
                
                
                    
                    
                
                
                    
                    
                
                
                
                
                    
                        
                        
                        
                        
                    
                
                
                
                    
                    
                        
                        
                            
                        
                        
                            
                        
                    
                
                
                
                    
                        
                    
                
            
        
        ④.web service 处理复杂数据
            1. 数组集合(List,Set,Map)
            2. 自定义类型
            
⑤. 一次web service请求的流程(以请求getStudentById(int id)它为例)
    
1. 客户端调用:helloWS.getStudentById(1),根据wsdl文档生成一个xml片断
    
    
        
            
                1
            
        
    
2. 将上面的xml数据作为请求体,向服务器发送一个http请求(即soap消息, in消息)
3. 服务器端接收到这个请求后,取出请求体的内容
4. 服务器解析请求体,得到数据,并调用对应的web service对象的方法(依据wsdl文档)
5. 将方法执行的返回值,根据wsdl文档生成一个新的xml片断:
    
        
            
                
                    12
                    1
                    Jack
                
            
        
    
6. 将新xml片断作为响应体,返回给客户端(soap消息, out消息)
7. 客户端接收到响应数据,解析其响应体中的xml片断,封装成student对象
8. 将生成的student对象作为helloWS.getStudentById(1)的返回值,整个请求结束

    3 拦截器
        为了让程序员能访问或修改soap消息中的内容,cxf设计的拦截器
        ①系统拦截器
            服务器端拦截器:
                //通过终端类将helloWS对象发布到address上
                EndpointImpl endpoint = (EndpointImpl) Endpoint.publish(address, helloWS);
                //在服务器端添加一个日志的in拦截器
                endpoint.getInInterceptors().add(new LoggingInInterceptor());
                //在服务器端添加一个日志的out拦截器
                endpoint.getOutInterceptors().add(new LoggingOutInterceptor());
            客户端拦截器:
                //创建生成SEI实现对象的工厂
                HelloWSImplService factory = new HelloWSImplService();
                //得到web service的SEI的实现类对象(动态生成的对象)
                HelloWS helloWS = factory.getHelloWSImplPort();
                //得到客户端对象
                Client client = ClientProxy.getClient(helloWS);
                //添加客户端的out拦截器
                client.getOutInterceptors().add(new LoggingOutInterceptor());
                //添加客户端的in拦截器
                client.getInInterceptors().add(new LoggingInInterceptor());
                Student s = helloWS.getStudentById(1);
                System.out.println("返回 "+s.getName());
        ②自定义拦截器
            AbstractPhaseInterceptor:抽象过程拦截器,一般自定义的拦截器都会继承于它
            功能:通过自定义拦截器实现用户名和密码的检查
                1. 服务器端:
                    设置in拦截器,从soap消息中获取用户名和密码数据,如果不满足条件就不执行web service的方法
                    public class MyIntercept extends AbstractPhaseInterceptor {
                        public MyIntercept() {
                            super(Phase.PRE_PROTOCOL);
                        }
                        @Override
                        public void handleMessage(SoapMessage msg) throws Fault {
                            System.out.println("-----handleMessage");
                            
                            Header header = msg.getHeader(new QName("atguigu"));
                            if(header==null) {
                                throw new Fault(new RuntimeException("用户名密码不存在 "));
                            } else {
                                Element data = (Element) header.getObject();
                                if(data==null) {
                                    throw new Fault(new RuntimeException("用户名密码不存在22"));
                                } else {
                                    String name = data.getElementsByTagName("name").item(0).getTextContent();
                                    String password = data.getElementsByTagName("password").item(0).getTextContent();
                                    if(!"xfzhang".equals(name) || !"amomo163".equals(password)) {
                                        throw new Fault(new RuntimeException("用户名密码不正确"));
                                    }
                                }
                            }
                            System.out.println("通过拦截器了!");
                        }
                    }
                2. 客户端:
                    设置out拦截器,向soap消息中添加用户名和密码数据
                    public class MyIntercept extends AbstractPhaseInterceptor {
                        private String name;
                        private String password;

                        public MyIntercept(String name, String pasword) {
                            super(Phase.PRE_PROTOCOL);
                            this.name = name;
                            this.password = pasword;

                        }

                        @Override
                        public void handleMessage(SoapMessage msg) throws Fault {
                            System.out.println("-----handleMessage");
                            Document document = DOMUtils.createDocument();
                            //
                            Element atguiguEle = document.createElement("atguigu");
                            //xfzhang_amomo163
                            Element nameEle = document.createElement("name");
                            nameEle.setTextContent(name);
                            
                            //xfzhang_amomo163
                            Element passwordEle = document.createElement("password");
                            passwordEle.setTextContent(password);
                            
                            atguiguEle.appendChild(nameEle);
                            atguiguEle.appendChild(passwordEle);
                            
                            //添加为请求消息的
                            msg.getHeaders().add(new Header(new QName("atguigu"), atguiguEle));
                        }

                    }

                    
                3. 说明:用户名和密码是以xml片断的形式存放在soap消息中的
                    
                        
                            
                                xfzhang
                                amomo163
                            
                        
                        
                            
                                1
                            
                        
                    
    
    ④用cxf做基于spring的web service开发
        server端:
            1. 新建web工程,导入cxf的jar包
            2. 定义SEI和其实现
                @WebService
                public interface OrderService {

                    @WebMethod
                    public Order getOrderByNo(String orderNo);
                }
                
                @WebService
                public class OrderServiceImpl implements OrderService {

                    public OrderServiceImpl() {
                        System.out.println("OrderServiceImpl()");
                    }

                    @Override
                    public Order getOrderByNo(String orderNo) {
                        System.out.println("getOrderByNo() orderNO=" + orderNo);
                        return new Order(3, orderNo, 10000000);
                    }

                }
                
                public class Order {

                    private int id;
                    private String orderNo;
                    private double price;
                }
            3. 发布web service
                beans.xml
                    
                    
                                    
                        
                        
                        
                        
                        
                        

                    
                web.xml
                    
                    
                      day101_ws_spring
                      
                        index.html
                        index.htm
                        index.jsp
                        default.html
                        default.htm
                        default.jsp
                      
                      
                      
                      
                          contextConfigLocation
                          classpath:beans.xml
                       
                       
                       
                       
                          
                             org.springframework.web.context.ContextLoaderListener
                          
                       
                       
                       
                       
                          CXFServlet
                          
                             org.apache.cxf.transport.servlet.CXFServlet
                          
                          1
                       
                       
                          CXFServlet
                          /*
                       
                       
                    
        
        client端
            1. 新建web工程,导入cxf的jar包
            2. 根据wsdl文档生成客户端代码(src下)
            3. client-beans.xml
                    
                    
                    
                
            4. 编写测试代码:
                public static void main(String[] args) {
                    //加载client-beans.xml
                    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                            "client-beans.xml");
                    //根据bean的id加载所对应的OrderService
                    OrderService orderService = (OrderService) context.getBean("orderClient");
                    //调用方法,发送soap请求
                    Order order = orderService.getOrderByNo("hao123");
                    System.out.println("client " + order.getId() + "_" + order.getOrderNo()
                            + "_" + order.getPrice());
                }
    5. 添加拦截器
        客户端:
            
                
                    
                        
                        
                    
                
            
        服务器端:
            
                
                    
                
            
补充:
    1. 用ajax访问webservice
        a. 使用原生的ajax : ajax.jsp
        b. 使用jquery的ajax : ajax2.jsp

    2. 用HttpURLConnection访问web service : HttpServletConnectionTest
                
Web Service好比一个服务供应商,给其他厂家提供基础服务,其他厂家再将这个服务包装成自己的产品或者服务提供给别人或自己使用。既然两个公司需要合作,不可能靠一句话就可以的,就需要一些标准和规范的东西来实现。那么:

SOAP 就像两个公司之间签的合同,约束双方按一定规矩和标准办事。

WSDL 则像说明书,告诉别人你有什么,能给别人提供什么服务。

你可能感兴趣的:(wsdl说明文档)