zoukankan      html  css  js  c++  java
  • Webservice与CXF框架快速入门

    1. Webservice

    Webservice是一套远程调用技术规范

    远程调用RPC, 实现了系统与系统进程间的远程通信.
    java领域有很多可实现远程通讯的技术,如:RMI(Socket + 序列化)、Binary-RPC(Http+二进制, 代表Hessian)、XML-RPC(Http+XML, 代表Burlap, WebService用的SOAP)、JMS(使用消息机制)、Mina(使用NIO)等, 底层都是基于http/socket和网络IO来实现的.
    从效率上来讲, RMI > Hessian >> Burlap >> web service.

    构成webservice的几个要素:

    1.WSDL:web服务描述语言. 即webservice服务的使用说明书, 自动生成,无需编写

    通过访问类似http://127.0.0.1:12345/weather?wsdl的地址可以查看
    它长如下这样子, 阅读顺序从下往上


    2.SOAP:简单对象访问协议   http post + xml
    必有 envelope 标签,将XML文档标识为一条 SOAP 消息
    必有 body 标签,传输的信息
    可选 header 标签,包含头部信息
    可选 fault 标签,提供有关在处理此消息所发生错误的信息


    SOAP常用有1.1, 1.2两个版本. jdk的Jaxws只支持发布SOAP1.1服务.

    如要SOAP1.2服务, 需要引入jaxws-ri, 并在实现类上加入注解@BindingType(SOAPBinding.SOAP12HTTP_BINDING)

    3.UDDI:提供webservice服务的注册和搜索功能, 不实用

    服务端

    public interface WeatherInterface {
        public String queryWeather(String cityName);
    }
    // 实现类前加WebService注解
    //@BindingType(SOAPBinding.SOAP12HTTP_BINDING) @WebService public class WeatherImpl implements WeatherInterface { @Override public String queryWeather(String cityName) { String weather = "晴"; return weather; } }
    public class WeatherServer {
        public static void main(String[] args) {
            //Endpoint发布服务, 参数1: 服务地址, 参数2: 服务实现类
            Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherImpl());
        }
    }

    对于定义的服务实现类, 可以用注解进行修饰

    @WebService 定义服务,在类上边

    targetNamespace:指定命名空间

    name:portType的名称

    portName:port的名称

    serviceName:服务名称

    endpointInterface:如果一个服务类实现了多个服务接口,但只需要发布一个接口的方法,可通过此注解指定要发布服务的接口

    @WebMethod 定义方法,在方法上边

    operationName:方法名

    exclude:设置为true表示此方法不是webservice方法,不会发布,默认是false

    @WebResult 定义返回值,在方法返回值前边

    name:返回结果值的名称

    @WebParam 定义参数,在方法参数前边

    name:指定参数的名称

    客户端

    首先, 用命令wsimport -s . http://127.0.0.1:12345/weather?wsdl生成支持类, 导入工程中

    第一种使用方式 使用相关类

    public class Client1 {
    
        public static void main(String[] args) throws IOException {
            // WSDL的地址, 非服务地址
            URL url = new URL("http://127.0.0.1:12345/weather?wsdl");
            //创建服务名称
            //参数一: namespaceURI – WSDL文档中  types/targetNamespace
            //参数二: localPart - 服务视图名, WSDL文档中 service-name
            QName qname = new QName("http://WebXml.com.cn/", "WeatherWS");
            //创建服务视图
            //参数1: wsdlDocumentLocation  WSDL地址
            //参数2: serviceName  服务名称
            Service service = Service.create(url, qname);
            //获取服务类  getPort(WSDL文档中portType-name)
            WeatherWSSoap weatherWSSoap = service.getPort(WeatherWSSoap.class);
            //调用方法   WSDL文档中portType-operation-name
            String result = weatherWSSoap.queryWeather("北京");
            System.out.println(result);
        }
    }

    第二种使用方式  http工具访问

    public class Client2 {
    
        public static void main(String[] args) throws IOException {
            // 服务地址
            URL url = new URL("http://127.0.0.1:12345/weather");
            // 创建连接对象
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置参数
            // Http发送方式:POST必须大写
            connection.setRequestMethod("POST");
            // content-type
            connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
            // 设置输入输出,默认connection没有读写权限,
            connection.setDoInput(true);
            connection.setDoOutput(true);
            // 发送请求
            String soapXML = getXML("北京");
            OutputStream os = connection.getOutputStream();
            os.write(soapXML.getBytes());
            // 接收响应
            int responseCode = connection.getResponseCode();
            if(200 == responseCode){
                InputStream is = connection.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                
                StringBuilder sb = new StringBuilder();
                String temp = null;
                while(null != (temp = br.readLine())){
                    sb.append(temp);
                }
                System.out.println(sb.toString());
                
                is.close();
                isr.close();
                br.close();
            }
            os.close();
        }
        
        // 组织SOAP数据
        public static String getXML(String cityName){
            String soapXML = "<?xml version="1.0" encoding="utf-8"?>"
            +"<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">"
                +"<soap:Body>"
                +"<getWeatherInfo xmlns="http://WebXml.com.cn/">"
                    +"<cityName>"+cityName+"</cityName>"
                  +"<userID></userID>"
                +"</getWeatherInfo>"
              +"</soap:Body>"
            +"</soap:Envelope>";
            return soapXML;
        }
    }

    第三种使用方式  浏览器访问

    <!doctype html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <script type="text/javascript">
        function queryWeather() {
            var xhr = new XMLHttpRequest();
            xhr.open("post", "http://127.0.0.1:12345/weather", true);
            xhr.setRequestHeader("content-type","text/xml;charset=utf-8");
            //设置回调函数
            xhr.onreadystatechange=function(){
                if(4 == xhr.readyState && 200 == xhr.status){
                    alert(xhr.responseText);
                }
            }
            //组织SOAP协议数据
            var soapXML = "<?xml version="1.0" encoding="utf-8"?>"
            +"<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">"
                +"<soap:Body>"
                +"<getWeatherInfo xmlns="http://WebXml.com.cn/">"
                    +"<cityName>"+document.getElementById("cityName").value+"</cityName>"
                  +"<userID></userID>"
                +"</getWeatherInfo>"
              +"</soap:Body>"
            +"</soap:Envelope>";
            //发送数据
            xhr.send(soapXML);
        }
      </script>
     </head>
     <body>
           天气查询:<input type="text" id="cityName"/> <input type="button" value="查询" onclick="javascript:queryWeather();"/>
     </body>
    </html>

    2. CXF框架

    CXF是一个开源的webservice框架
    CXF支持SOAP1.1/1.2,REST 协议
    CXF支持XML,JSON(仅REST下) 的数据格式

    服务端  JAX-WS方式(SOAP)

    //@BindingType(SOAPBinding.SOAP12HTTP_BINDING)  默认发布SOAP1.1, 该注解发布SOAP1.2
    @WebService
    public interface WeatherInterface {
        public String queryWeather(String cityName);
    }
    public class WeatherImpl implements WeatherInterface {
        @Override
        public String queryWeather(String cityName) {
            String weather = "晴";
            return weather;
        }
    }
    //与spring整合后可不要该类
    public class WeatherServer {
        public static void main(String[] args) {
            JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
            //设置服务接口
            jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class);
            //设置服务实现类
            jaxWsServerFactoryBean.setServiceBean(new WeatherImpl());
            //设置服务地址
            jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/ws/weather");
            //发布
            jaxWsServerFactoryBean.create();
        }
    }

    与web整合, spring+CXFservlet替代WeatherServer类

    <?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"
        xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
                                http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
                                http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
        
        <!-- 服务实现类 -->
        <bean id ="weatherImpl" class="com.zx.server.WeatherImpl"/>
         
        <!-- 拦截器  --
        <bean id ="inIntercepter" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
        <bean id ="outIntercepter" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
        -->
        
        <!-- 方式1 用JaxWsServerFactoryBean发布SOAP协议的服务 -->
        <jaxws:server address="/weather" serviceClass="com.zx.server.WeatherInterface">
            <jaxws:serviceBean>
                <ref bean="weatherImpl"/>  <!-- 实现类 -->
            </jaxws:serviceBean>
            <!-- 配置拦截器 --
            <jaxws:inInterceptors>
                <ref bean="inIntercepter"/>
            </jaxws:inInterceptors>
            <jaxws:outInterceptors>
                <ref bean="outIntercepter"/>
            </jaxws:outInterceptors>
            -->
        </jaxws:server>
    
        <!-- 方式2 用Endpoint发布SOAP协议的服务 -->    
        <jaxws:endpoint address="/weather" implementor="com.zx.server.WeatherImpl"/>        
    </beans>

    endPoint 只支持发布实现类
    JaxWsServerFactoryBean还可以发布接口

    web.xml

      <!-- 配置CXF的Servlet -->
      <servlet>
          <servlet-name>CXF</servlet-name>
          <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>CXF</servlet-name>
          <url-pattern>/ws/*</url-pattern>
      </servlet-mapping>

    客户端

    首先, 类似wsimport, 使用CXF下的Wsdl2java生成支持类, 导入工程中

    public class WeatherClient {
        public static void main(String[] args) {
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            //设置服务接口
            jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class);
            //设置服务地址
            jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/ws/weather");
            //获取服务接口, 可与spring整合替代
            WeatherInterface weatherInterface = jaxWsProxyFactoryBean.create(WeatherInterface.class);
            //调用查询方法
            String weather = weatherInterface.queryWeather("保定");
            System.out.println(weather);
        }
    }

    与spring整合后由spring生成weatherInterface实例

      <!-- 用JaxWsProxyFactoryBean建立客户端 -->    
        <jaxws:client id="weatherClient" address="http://127.0.0.1:12345/ws/weather" serviceClass="com.zx.WeatherInterface"/>

    服务端  JAX-RS方式(REST风格)

    基础bean

    @XmlRootElement(name="student")  //能被格式化为XML
    public class Student {
        private long id;
        private String name;
        private Date birthday;
        public getXXX(), setXXX();  // get set方法
    }

    服务接口

    @WebService
    @Path("/student") //将请求路径“/student”映射到接口上
    public interface StudentInterface {
    
        @POST // 指定请求方式 GET / POST
        @Produces(MediaType.APPLICATION_XML) //指定服务数据类型 XML / JSON
        @Path("/query/{id}")  //将请求路径/query映射到方法上, 参数注入配合@PathParam注解
        public Student query(@PathParam("id")long id);
        
        @GET
        @Produces({"application/json;charset=utf-8",MediaType.APPLICATION_XML})  //同时指定json和xml, 添加访问参数?_type=json返回json; 添加?_type=xml返回XML
        @Path("/queryList/{name}")
        public List<Student> queryList(@PathParam("name")String name);
    }

    服务实现, 仅举例

    public class StudentImpl implements StudentInterface {
        @Override
        public Student query(long id) {
            Student st = new Student();
            st.setId(110);
            st.setName("张三");
            st.setBirthday(new Date());
            return st;
        }
    
        @Override
        public List<Student> queryList(String name) {
            Student st = new Student();
            st.setId(110);
            st.setName("张三");
            st.setBirthday(new Date());
            List<Student> list = new ArrayList<Student>();
            list.add(st);
            return list;
        }
    }

    发布

    public class StudentServer {
        public static void main(String[] args) {
            //JAXRSServerFactoryBean 发布REST的服务
            JAXRSServerFactoryBean jaxRSServerFactoryBean = new JAXRSServerFactoryBean();
            jaxRSServerFactoryBean.setServiceBean(new StudentImpl());
            jaxRSServerFactoryBean.setResourceClasses(StudentImpl.class);
            jaxRSServerFactoryBean.setAddress("http://127.0.0.1:12345/ws/user");
            jaxRSServerFactoryBean.create();
        }
    }

    与web整合, spring+CXFservlet替代StudentServer

    <?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"
        xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
                                http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
                                http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
        <!-- 配置服务实现类 -->
        <bean id = "studentImpl" class="com.zx.StudentImpl"/>
        
        <!-- 使用JAXRSServerFactoryBean发布REST的服务 -->    
        <jaxrs:server address="/user">
            <jaxrs:serviceBeans>
                <ref bean="studentImpl"/>
            </jaxrs:serviceBeans>
        </jaxrs:server>
    </beans>

    web.xml

      <!-- 配置CXF的Servlet -->
      <servlet>
          <servlet-name>CXF</servlet-name>
          <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>CXF</servlet-name>
          <url-pattern>/ws/*</url-pattern>
      </servlet-mapping>

    REST风格下WSDL访问网址为http://127.0.0.1:12345/ws/user?_wadl

  • 相关阅读:
    asp.net 微信企业号办公系统-流程设计--流程步骤设置-策略设置
    asp.net 微信企业号办公系统-流程设计--流程步骤设置-基本设置
    asp.net 微信企业号办公系统-流程设计-流程属性设置
    asp.net 微信企业号办公系统-表单设计-保存与发布
    asp.net 微信企业号办公系统-表单设计-数据表格
    asp.net 微信企业号办公系统-表单设计-子表
    asp.net 微信企业号办公系统-表单设计-附件管理
    asp.net 微信企业号办公系统-表单设计-日期时间选择
    asp.net 微信企业号办公系统-表单设计-组织机构选择
    asp.net 微信企业号办公系统-表单设计-数据字典选择
  • 原文地址:https://www.cnblogs.com/myJavaEE/p/6680659.html
Copyright © 2011-2022 走看看