<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    菠蘿三國

    大江東去,浪淘盡...
    隨筆 - 34, 文章 - 47, 評論 - 22, 引用 - 0
    數據加載中……

    Servlet與Web服務

    1.第一口就吃到餡,配置一個Web服務的最簡方法
    ===============================================================================================

    為了能讓web服務先跑起來,先給出一個Web服務的原型,以便于后面的討論。
    我們從一個最簡單的例子開始,只給出必須的東西。

    所需軟件:
    1.Tomcat4.1.2
    2.一個Java編譯器,jdk或JBuilder等等,這是為了編譯我們的Java源程序,于web服務無關。

    所需文件:
    1.sayHello.java
    2.web.xml
    3.server-config.xml
    4.Java Packages: axis.jar,jaxrpc.jar,tt-bytecode.jar,wsdl4j.jar,xercesImpl.jar,xml-apis.jar

    至于Tomcat怎么安裝我就不說了,網上關于Tomcat安裝的文章有很多。
    這六個package,從ibm和apache的網站上都可以下得到。

    只需要這些,我們就可以部署自己的Web服務了。。
    下面是目錄結構:
    webapps/test/WEB-INF/web.xml
    webapps/test/WEB-INF/server-config.wsdd
    webapps/test/WEB-INF/classes/sayHello.class
    webapps/test/WEB-INF/lib/xxx.jar ---所需得六個packages


    web.xml
    ---------------------------------------------

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

    <web-app>

    <servlet>
        <servlet-name>Axis</servlet-name>
        <!--實際servlet程序,這里是AxisServlet-->
        <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
    </servlet>

    <!-- ### 定義servlet和url的對應關系-->

    <servlet-mapping>
        <servlet-name>Axis</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>

    </web-app>

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

    server-config.wsdd
    ---------------------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    <deployment xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns="http://xml.apache.org/axis/wsdd/">

    <handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>
      
    <service name="sayHelloService" provider="java:RPC">
      <parameter name="className" value="sayHello"/>
      <parameter name="allowedMethods" value="sayHelloTo"/>
    </service>

    <transport name="http">
      <requestFlow>
        <handler type="URLMapper"/>
      </requestFlow>
    </transport>

    </deployment>
    ---------------------------------------------

    sayHello.java
    ---------------------------------------------
    public class sayHello
    {
      public String sayHelloTo(String aname)
      {
        return "How are you, " + aname;
      }
    }
    ---------------------------------------------


    假設ip地址192.168.0.1,端口號是80,我們輸入下面的url得到服務列表(當然這里只有一個):
    http://192.168.0.1/test/services
    如果你的端口號是8080,就應該輸入http://192.168.0.1:8080/test/services,后面同理。

    瀏覽器顯示:
    ——————————————
    |And now... Some Services |
    | sayHelloService (wsdl)  |
    |  .sayHelloTo            |   
    ——————————————

    sayHelloService是我們的服務名,右側的 (wsdl)是一個鏈接指向sayHelloService的WSDL文檔,
    這個文檔是由Axis自動生成的。
    sayHelloTo當然就是我們的方法了。。。

    點擊(wsdl)鏈接或輸入下面的url,得到WSDL:
    http://192.168.0.1/test/services/sayHelloService?wsdl

    瀏覽器顯示sayHelloService的WSDL文檔:

    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions targetNamespace="http://192.168.0.1/test/services/sayHelloService/test/services/sayHelloService" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://192.168.0.1/test/services/sayHelloService/test/services/sayHelloService-impl" xmlns:intf="http://192.168.0.1/test/services/sayHelloService/test/services/sayHelloService" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <wsdl:message name="sayHelloToResponse">
        <wsdl:part name="return" type="xsd:string"/>
      </wsdl:message>
      <wsdl:message name="sayHelloToRequest">
        <wsdl:part name="aname" type="xsd:string"/>
      </wsdl:message>
      <wsdl:portType name="sayHello">
        <wsdl:operation name="sayHelloTo" parameterOrder="aname">
          <wsdl:input message="intf:sayHelloToRequest" name="sayHelloToRequest"/>
          <wsdl:output message="intf:sayHelloToResponse" name="sayHelloToResponse"/>
        </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name="sayHelloServiceSoapBinding" type="intf:sayHello">
        <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="sayHelloTo">
          <wsdlsoap:operation soapAction=""/>
          <wsdl:input name="sayHelloToRequest">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://192.168.0.1/test/services/sayHelloService/test/services/sayHelloService" use="encoded"/>
          </wsdl:input>
          <wsdl:output name="sayHelloToResponse">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://192.168.0.1/test/services/sayHelloService/test/services/sayHelloService" use="encoded"/>
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name="sayHelloService">
        <wsdl:port binding="intf:sayHelloServiceSoapBinding" name="sayHelloService">
          <wsdlsoap:address location="http://192.168.0.1/test/services/sayHelloService"/>
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>



    我們甚至不用客戶端,就可以查看服務是否部署成功以及獲得返回結果
    用Get方法獲得soap流,我們要用下面的url:
    (真正調用Web服務,用的是Post方法,這個后面會講)

    http://192.168.0.1/test/services/sayHelloService?method=sayHelloTo&aname=everybody

    瀏覽器顯示的是亂碼,我們點右鍵查看源文件,結果如下:

    <p>Got response message</p>
    <?xml version="1.0" encoding="UTF-8"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <soapenv:Body>
      <sayHelloToResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
       <sayHelloToReturn xsi:type="xsd:string">How are you, everybody</sayHelloToReturn>
      </sayHelloToResponse>
     </soapenv:Body>
    </soapenv:Envelope>

    這就是我們想要的結果嗎?這只是服務器端送回來的SOAP消息,不過我們想要的結果在里面。。。


    為了真正調用我們的Web服務,下面給出一個Client:

    import org.apache.axis.client.Call;
    import org.apache.axis.client.Service;
    import javax.xml.namespace.QName;

      public class test
      {
        public static void main(String [] args)
        {
          try {
                 String endpoint = "http://192.168.0.1/test/services/sayHelloService";
                 Service  service = new Service();
                 Call     call    = (Call) service.createCall();
                 call.setTargetEndpointAddress( new java.net.URL(endpoint) );
                 call.setOperationName(new QName("http://sayHelloService", "sayHelloTo"));
                 String ret = (String) call.invoke( new Object[] { args[0] } );
                 System.out.println(ret);
             } catch (Exception e) {
                 e.printStackTrace();
             }
        }
      }

      注意要配置好正確的classpath,確保編譯器能找的到axis.jar和jaxrpc.jar,否則編譯不會通過。
      用下面的命令行運行這個class:
      java test everybody
      我們會得到:How are you, everybody

      這才是我們真正想要的。。。



    2.追根究底,我們的Web服務是怎樣跑起來的
    ===============================================================================================


    前面給出的兩個配置文件web.xml和server-config.wsdd,或許不是能一下子就看懂的。

    先讓我們回顧一下servlet的映射模式。

    我們知道,servlet是從javax.servlet.http.HttpServlet繼承的,在服務器端被載入JVM執行,然后向客戶端輸出html流。
    servlet的web.xml文件(位于 webapps/foo/WEB-INF目錄):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
                             "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
    <web-app>
    <servlet-mapping>
    <servlet-name>invoker</servlet-name>
    <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
    </web-app>


    invoker servlet 其實是:org.apache.catalina.servlets.InvokerServlet
    按類名提供小服務程序。例如,如果您調用 foo/servlet/HelloServlet,
    invoker servlet將裝入該HelloServlet(如果它在其類路徑中的話)并執行。

    初看上面的web.xml,好像只給出了一個servlet映射,而沒有定義invoker servlet。
    其實,invoker servlet 是在tomcat的conf目錄中的web.xml中定義的::
     <servlet>
            <servlet-name>invoker</servlet-name>
            <servlet-class>
              org.apache.catalina.servlets.InvokerServlet
            </servlet-class>
            <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
            </init-param>
            <load-on-startup>2</load-on-startup>
        </servlet>

    所以,如果拋開Tomcat_HOME/conf/web.xml,我們這樣定義一個web.xml,似乎更能清楚的說明問題:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
                             "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
    <web-app>
    <servlet-name>MyInvoker</servlet-name>
    <servlet-class>
    org.apache.catalina.servlets.InvokerServlet
    </servlet-class>
    <init-param>
    <param-name>debug</param-name>
    <param-value>0</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>MyInvoker</servlet-name>
    <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
    </web-app>


    即所有/servlet/* 模式的url,都會交給org.apache.catalina.servlets.InvokerServlet來處理。
    或者說,所有/servlet/* 模式的url,其實都是調用InvokerServlet這個類,而InvokerServlet本身也是
    一個servlet,它也是從 HttpServlet 繼承而來的。

    這樣,我們自己的servlet就能夠通過特定的url執行,即 /servlet/OurServlet。
    當然,如果你高興,可以定義任何的 url pattern,而不一定是 /servlet/*,這一點,正如我們后面
    看到的Axis處理Soap消息的方法。


    再進一步,如果不想讓 InvokerServlet 在中間“搗鬼”,我們當然可以直接定義自己的servlet:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
                             "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
    <web-app>
    <servlet-name>MyInvoker2</servlet-name>
    <servlet-class>
    com.foo.MyServlet
    </servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>MyInvoker2</servlet-name>
    <url-pattern>/AnyName/*</url-pattern>
    </servlet-mapping>
    </web-app>


    JSP也是一樣的道理,有了上面的分析,
    看看Tomcat_HOME/conf/web.xml中的如下語句就可以JSP的處理方法了,這里就不再廢話了:
    ....
    <servlet>
            <servlet-name>jsp</servlet-name>
            <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
            <init-param>
                <param-name>logVerbosityLevel</param-name>
                <param-value>WARNING</param-value>
            </init-param>
            <load-on-startup>3</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
    </servlet-mapping>
    ....


    下面進入正題。


    我們先來看部署Web Service的web.xml:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

    <web-app>

    <servlet>
        <servlet-name>Axis</servlet-name>
        <!--實際servlet程序,這里是AxisServlet-->
        <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
    </servlet>

    <!-- ### 定義servlet和url的對應關系-->

    <servlet-mapping>
        <servlet-name>Axis</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>

    </web-app>


    所有 /services/* 模式的 url 都會交給org.apache.axis.transport.http.AxisServlet處理,
    AxisServlet當然也是從HttpServlet繼承而來的。這就是為什么我們部署的Web服務在調用時都要在
    服務名稱前加上 services/ 了。

    可以說,AxisServlet是所有Web服務調用的入口。
    那么AxisServlet在接手Web服務調用后都做了哪些工作呢?

    客戶端用call.invoke()調用web服務用的是POST,所以入口是AxisServlet.doPost...
    而不是AxisServlet.doGet...


    先來看看AxisServlet的doPost函數,這里只給出了關鍵語句及注釋:

        /**
         * Process a POST to the servlet by handing it off to the Axis Engine.
         * Here is where SOAP messages are received
         * @param req posted request
         * @param res respose
         * @throws ServletException trouble
         * @throws IOException different trouble
         */
         public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException
        {
    msgContext = createMessageContext(engine, req, res);//獲取客戶請求信息

    engine.invoke(msgContext); //調用客戶端請求的服務

    responseMsg = msgContext.getResponseMessage();//得到調用的返回結果

    sendResponse(getProtocolVersion(req), contentType, res, responseMsg);//將結果送至客戶端
         }

    這樣一來,Web服務調用的來龍去脈就大致清楚了。。。

    為了高清楚前面我們的三個url
    http://192.168.0.1/test/services
    http://192.168.0.1/test/services/sayHelloService?wsdl
    http://192.168.0.1/test/services/sayHelloService?method=sayHelloTo&aname=everybody
    是怎樣獲得輸出結果的,再來看看AxisServlet的doGet函數,這里只給出了流程框架及注釋:

    **
    * Process GET requests. Because Axis does not support the GET-style
    * pseudo execution of SOAP methods, this handler deals with queries
    * of various kinds, not real SOAP actions.
    *
    * @todo for secure installations, dont stack trace on faults
    * @param request request in
    * @param response request out
    * @throws ServletException
    * @throws IOException
    */
    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException
    {

    //如果路徑為空,比如:http://localhost/wstk/services 或 http://localhost/wstk/services/*
    if((pathInfo == null || pathInfo.equals("")) && !realpath.endsWith(".jws"))

    {
    //從server-config.wsdd文件中讀取所有部署的服務信息,向向客戶端列出所有部署的服務,
    //包括每個服務可調用的方法。

    }else
    //如果路徑不為空,比如:http://localhost/wstk/services/sayHelloService
    if(realpath != null)
    {
    //如果請求wsdl,比如:http://localhost/wstk/services/sayHelloService?wsdl
    if(wsdlRequested)
    {
    //創建sayHelloService的WSDL文件并傳送至客戶端
    } else
    //這里是利用url調用Web服務的入口,比如http://192.168.0.1/test/services/sayHelloService?method=sayHelloTo&aname=everybody
    if(req.getParameterNames().hasMoreElements())
    {
    //如果客戶端調用的方法正確,則Axis會調用相應的JavaBean,并把JavaBean的返回結果
    //封裝為Soap消息流返回給客戶端。
    }
    }
    }


    而Axis怎樣找到我們所請求的JavaBean呢?答案是server-config.wsdd文件。

    server-config.wsdd

    <?xml version="1.0" encoding="UTF-8"?>
    <deployment xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns="http://xml.apache.org/axis/wsdd/">

    <service name="sayHelloService" provider="java:RPC">
      <parameter name="className" value="sayHello"/>
      <parameter name="allowedMethods" value="sayHelloTo"/>
    </service>

    <handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>

    <transport name="http">
      <requestFlow>
        <handler type="URLMapper"/>
      </requestFlow>
    </transport>

    </deployment>

    WSDD是web service deployment descriptor的縮寫。

    最外面的<deployment>元素指示這是WSDD,并定義了java的名字空間。

    接著的 <service>元素定義了service。一個service是一個目標鏈,包括請求request、內容提供者provider、響應response。
    在這個例子中,我們指出service名字是sayHelloService ,provider是"java:RPC",它是axis 的標記,指示這是一個java的RPC service,
    而處理它的真正的class是org.apache.axis.providers.java.RPCProvider。

    接著我們要在<parameter>中告訴RPCProvider,它如何實例化并調用正確的class(如:com.foo.MyService)。
    <parameter>元素的className指示class名,allowedMethods告訴引擎那些共用的方法要通過soap來調用。
    "*"表示所有的公共方法,我們也列出方法名字列表,可以空格或逗號分割它們。

    posted on 2007-08-06 22:23 菠蘿 閱讀(298) 評論(0)  編輯  收藏 所屬分類: AXIS

    主站蜘蛛池模板: 国产a级特黄的片子视频免费| 精品无码免费专区毛片| 免费a级毛片网站| 亚洲精品无码久久久久久| 成年女人午夜毛片免费看| 亚洲区日韩精品中文字幕| 国内外成人免费视频| 国产精品无码亚洲精品2021| 国产大片免费观看中文字幕| 亚洲第一成年免费网站| 免费jjzz在线播放国产| 日韩精品免费一线在线观看| 国产精品亚洲mnbav网站| 人人爽人人爽人人片A免费| 免费成人在线观看| 爱情岛论坛免费视频| 中文字幕亚洲天堂| 一区二区三区无码视频免费福利| 久久亚洲高清观看| 国内精自视频品线六区免费| 亚洲国产乱码最新视频| 免费无码又爽又刺激毛片| 美女视频黄a视频全免费网站一区 美女视频黄a视频全免费网站色 | 免费无码专区毛片高潮喷水| 中文字幕影片免费在线观看| 一级毛片全部免费播放| 亚洲国产成人在线视频| 免费看韩国黄a片在线观看| 亚洲AV第一成肉网| 亚洲av中文无码| 久久免费观看国产精品88av| 亚洲理论片在线中文字幕| 97人伦色伦成人免费视频| 四虎一区二区成人免费影院网址 | 韩国免费一级成人毛片| 亚洲色在线无码国产精品不卡| 亚洲国产精品一区二区三区久久| 99视频在线免费观看| 亚洲乱码卡一卡二卡三| 亚洲伊人成无码综合网| 18级成人毛片免费观看|