servlet,jsp,axis webservice 的實現原理

來源:互聯網
上載者:User

引用網路上一個好文

servlet,jsp,axis webservice 的實現原理

回顧一下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來調用。
"*"表示所有的公用方法,我們也列出方法名字列表,可以空格或逗號分割它們。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.