webservice

来源:互联网 发布:structure软件 使用 编辑:程序博客网 时间:2024/04/30 14:51

WebService 概述
网络服务,是RPC 的一种实现方式
客户端要调用 必须遵循 TCP协议, 而 WebService 使用更高以及的 HTTP协议; — 用来获取数据,数据本身必须是
WS是一种基于 Http协议和XML技术,并使用 WSDL描述和使用SOAP协议传输的异构系统解决方案

拓展:    webService三要素:SOAP、WSDL(WebServicesDescriptionLanguage)、UDDI(UniversalDescriptionDiscovery andIntegration)        SOAP  ---  用来描述传递信息的格式,         WSDL ---  用来描述如何访问具体的接口,         UDDI  ---  用来管理,分发,查询webService    RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。    SOAP(简单对象访问协议):是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。应用场景:        1. 由权威机构提供的第三方小功能;        2. 多客户端的整合        针对不同的平台提供不同的客户端,而这些客户端获取数据,使用 RPC,WS就是一种实现方式;        3. 异构系统的整合(跨语言、跨系统)        企业信息化战略规划中常见问题: 信息孤岛(各个系统之间信息不互通)            解决方案: 直接让一个系统提供数据,其他系统远程访问   、  企业服务总线(ESB)---  发布到总线,其他系统远程访问总线                ESB知识扩展            SOA   --  面向服务的架构                WSDL :描述服务                UDDI  : 目录服务,查找服务                SOAP  : 简单对象访问协议,调用服务的协议    WS和SOA的区别:        Web Service是技术规范,而SOA是设计原则,一种架构模式。        WSDL,UDDI和SOAP是SOA基础的基础部件。        WSDL:用来描述服务;        UDDI:用来注册和查找服务;        SOAP:作为传输层,用来在客户端和服务器端之间传送消息。

基于 JDK 的 WS

服务端    构建服务        标准在类上            @WebService                                         //标记为WS服务类            @SOAPBinding(style=Style.RPC)          //声明访问规范   ,默认 document         标注在方法上            @WebMethod                                      //标记为需要暴露的WS服务方法    发布服务        使用JDK中的Endpoint类发布服务,            public static Endpoint publish(String address,Object implementor)            参数:                address -一个URI,指定要使用的地址和传输/协议。                implementor -服务实现类。            返回:            新创建的服务端端点。        发布后的xml 中:            WSDL                    service  -----   确定服务发布的名称和 服务地址                      binding  ----                            transport  --- 指定传输协议                            style          --- 定义整个 wsdl文档的编写规范                            operation  --- 描述了服务方法                    portType  ---  对服务的方法进行详细描述                    message  ---  定义方法传入的参数,返回值                    types  ---  只对document有效,RPC不会存在    定义类型            WSDL :                用来描述WS和说明如何与WS通信的XML语言,即基于XML的语言的,用于描述Webservice及其方法、参数和返回值的一种语言,服务交互所需的所有细节都位于其WSDL文件中。 客户端 (远程调用服务 ) -- 创建单独项目     使用 在%JAVA_HOME%\bin下的   wsimport.exe工具 生成客户端代码         生成过程中 ,服务端应该处于开启状态        %JAVA_HOME%\bin 配置在 环境变量path中     步骤:         1) 使用wsimport生成客户端代码            wsimport -s . http://192.168.1.3:9999/weather?wsdl            注意:服务端不能关闭           wsimport所在%JAVA_HOME%\bin,这个路径要放到path中,方便调用。                        在客户端代码src下面执行命令         2) 使用生成的类编写代码完成对服务端的调用            //getWeatherServicePort 这个方法会生成一个WeatherService的代理对象,完成对服务端的调用。            WeatherService weatherService =                     new WeatherServiceService().getWeatherServicePort();            System.out.println(weatherService.getClass().getName());            //通过代理完成远程调用            String weather = weatherService.getWeather("");            System.out.println(weather);            SOAP,调用远程方法和响应都是以SOAP的消息实现的。              Envelope 信封                  header 头部,有的ws是需要收费的。一般当你给钱后,就给你发用户名和密码。ws服务端就要完成登录校验需要客户端传递用户名和密码。                                                  就可以把用户名和密码放到头部。                  body  主体,完成调用方法和传入参数说明,已经响应值的描述。 WebService常见标签详解     代码详解    @WebService标签        endpointInterface:定义服务抽象WebService 协定的服务端点接口的完整名称。不允许在端点上使用此成员值,该元素的值必须有                        WebService标签。默认情况下,服务器自动生成服务端接口。        name:服务接口名称(对应wsdl: portType的name属性,用在服务接口上);        serviceName:服务类名称。默认为,实现类名+Service(对应service的name和definition上的name属性对应,用在实现类上)。        portName:Web Service的端口名称。此名称被用作wsdl:port的名称。        targetNamespace:目标命名空间,描述服务的预定义WSDL的位置(同时用在实现类和服务接口上,需统一)。        wsdlLocation:WSDL地址(服务端除了WSDL优先的情况外可不写,客户端代理接口上必须配置此属性,指向web端WSDL文件地址)         只要在 类上添加了此标签,该类中的所有方法默认都会暴露出去 ; 要暴露指定的方法,需要手动配置            不暴露的方法上添加   @WebMethod(exclude=true)  -- 置于接口中的方法上才会生效,实现类不行         只要配置 endpointInterface , 想要修改属性,必须在 接口中修改才可以    @WebMethod标签        operationName:指定暴露服务方法的别名。        exclude:是否暴露此标记的方法。    @WebResult标签        name:定义返回值的名称。        header:布尔类型,是否把值放到header元素中进行传递。        @WebResult(name="result")String SayYes(@WebParam(name="name") String name);    @SOAPBinding        SOAPBinding.ParameterStyleparameterStyle 确定方法参数是否表示整个消息正文,或者参数是否是包装在以操作命名的顶层元素中的元素。        SOAPBinding.ParameterStyle.WRAPPED,默认,使用对参数进行包装        SOAPBinding.ParameterStyle.BARE,不对参数进行包装        SOAPBinding.Style style 定义发 送到Web Service 的消息 和从Web Service发送的消息的编码样式。        SOAPBinding.Style.RPC:面向RPC        SOAPBinding.Style.DOCUMENT 默认,面向文档        SOAPBinding.Useuse 定义发送到WebService的消息和从WebService发送的消息的格式样式。        SOAPBinding.Use.LITERAL,默认,字面量风格,若服务端和客户端不在一起开发,就应该使用这个        SOAPBinding.Use.ENCODED使用SOAP编码风格,可能导致WS互操作方面失败问题,尽量避免使用。    实践总结:        /**         * endpointInterface : 定义服务抽象WebService 协定的服务端点接口的权限命名, 对应接口上也要标注 @WebService         * name:服务接口名称(对应wsdl: portType的name属性,用在服务接口上);         * portName : Web Service的端口名称。此名称被用作wsdl:port的名称  --- 标注在实现类上         * serviceName : 服务类名称。默认为,实现类名+Service(  对应service的name  和    definition上的name属性    对应,用在实现类上)         * targetNamespace : 目标命名空间  -- 实现类和接口上都要标注         * wsdlLocation :WSDL地址(服务端除了WSDL优先的情况外可不写,客户端代理接口上必须配置此属性,指向web端WSDL文件地址)         * @SOAPBinding(style=Style.RPC) : 声明访问规范   ,默认 document ,         *      当定义了服务抽象webservice协定的服务端点接口时,必须标注在接口上,否则会被忽略         */

CXF
是 XFire 和 Celtrix 的整合
优点:
是 SOA框架(面向服务编程) — ws只会用到 XFire
CXF内置 Jetty Web 服务器
使用CXF开发Web Server端组件都需要“接口”和“实现类”两部分。
支持多种数据格式:XML和JSON(Restful)。
可以与Spring进行快速无缝的整合
灵 活 的 部 署 : ant(build.xml) maven(pom.xml)
可 以 运 行 在 Tomcat , Jboss , Jetty(内 置web 服 务器) , IBMWebsphere , BeaWebLogic 上面。

下载官网: http://cxf.apache.org/ CXF 需要 配置 对应的 bin 到 环境变量path 中导包:    asm 是字节码相关的包;    logging 是日志相关的包;    cxf 是框架核心包;    geronimo-servlet    是servlet相关包;    neethi  是网络安全相关包;    wsdl4j  是wsdl解析用的包;    xmlschema   是schema相关的包。    jetty服务器相关包     wsdl2java工具  ---  客户端代码生成工具    -d参数,指定代码生成的目录。    -p参数,指定生成的新的包结构。    在控制台执行:        wsdl2java –d . -p org.leiax00.cxf http://192.168.1.3:9999/hello?wsdl    也可以进入客户端项目的src下执行命令:        wsdl2java http://192.168.1.3:9999/hello?wsdl 通过 CXF 创建 服务端        1. 创建项目        2. 导入 cxf 的必须包,同时没有容器时还要导入jetty的包        3. 写代码测试            1) 写一个普通服务类            2) 标注注解, 成为一个 ws 服务类            3) 使用cxf来发布                //1. 创建JaxWsServerFactoryBean的对象,用于发布服务                JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();                //2. 设置服务发布地址                jaxWsServerFactoryBean.setAddress("http://192.168.1.3:9999/hello");                //3. 设置服务发布接口                jaxWsServerFactoryBean.setServiceClass(IHelloService.class);                //4. 设置服务发布对象                jaxWsServerFactoryBean.setServiceBean(new HelloServiceImpl());                //5. 设置拦截器                jaxWsServerFactoryBean.getInInterceptors().add(new AuthInInterceptor());                jaxWsServerFactoryBean.getInInterceptors().add(new LoggingInInterceptor());                //6. 通过create方法发布服务                jaxWsServerFactoryBean.create();                System.out.println("发布成功!!");            4) 测试 --- wsdl地址时候能访问 通过 CXF 生成 客户端    通过 wsdl2java 工具生成客户端代码,在src目录下运行cmd: wsdl2java http://192.168.1.3:9999/hello?wsdl        生成后,只保留接口类 ,其余删除    ---  此时接口类报错  (@XmlSeeAlso({ObjectFactory.class})) ,将此注解也删除    获取服务:        1.创建JaxWsProxyFactoryBean的对象,用于接收服务        2.设置服务的发布地址,表示去哪里过去服务        3.设置服务的发布接口,使用本地的代理接口        4.通过create方法返回接口代理实例        5.调用远程方法
public static void main(String[] args) {    //1. 创建JaxWsProxyFactoryBean的对象,用于接收服务    JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();    //2. 设置服务的发布地址,表示去哪里过去服务        jaxWsProxyFactoryBean.setAddress("http://192.168.1.3:9999/hello");    //3. 设置服务的发布接口,使用本地的代理接口jaxWsProxyFactoryBean.setServiceClass(IHelloService.class);    //4. 添加拦截器                  jaxWsProxyFactoryBean.getOutInterceptors().add(new AuthOutInterceptor("admin", "root"));    //4. 通过create方法返回接口代理实例    IHelloService helloService = (IHelloService)jaxWsProxyFactoryBean.create();    //5. 调用服务端的方法(远程)    helloService.sayHello("李雷");}
 CXF 自定义拦截器   ---  权限控制     1、声明一个类,来充当拦截器。这个类需要继承或实现某个接口或基类 , 一般直接继承    AbstractPhaseInterceptor类 。    2、完成拦截器的逻辑。    3、把拦截器配置到环境中。    使用自带的日志拦截器: --- 可监控到  soap消息        LoggingInInterceptor–信息输入时的拦截器-请求            LoggingOutInterceptor–信息输出时的拦截器-响应    服务端通过   
jaxWsServerFactoryBean.getInInterceptors().add(new LoggingInInterceptor());
    来添加拦截器    客户端通过

jaxWsProxyFactoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
来添加拦截器

    获取当前调用的方法   ---  soap的body中存储了当前调用的方法    //4. 获取当前调用的方法
Exchange exchange = message.getExchange();  BindingOperationInfo bop = exchange.get(BindingOperationInfo.class);  MethodDispatcher md = (MethodDispatcher) exchange.get(Service.class).get(MethodDispatcher.class.getName());  Method method = md.getMethod(bop);  System.out.println("********method name:" + method.getName());
0 0
原创粉丝点击