Tomcat(二) Tomcat實現: Servlet與web.xml介紹 以及 原始碼分析Tomcat實現細節
轉載自;http://blog.csdn.net/tjiyu/article/details/54590259
-------如有侵權 請聯絡我 我會進行刪除在《Tomcat(一) Tomcat是什麼:Tomcat與Java技術 Tomcat與Web應用 以及Tomcat基本框架及相關配置》對Tomcat有了一個大體的認識,下面將深入瞭解Tomcat技術的實現:
1、先來了解JavaEE Servlet技術的一些物件元件;
2、再來了Web應用程式部署檔案web.xml中對Servlet元件的定義;
3、最後再從Tomcat原始碼分析一些實現細節,重點關注:Tomcat的啟動/初始化、併發執行緒模式、接收請求與處理、以及Servlet容器的實現。
1、JavaEE Servlet技術
Tomcat是一個Servlet容器,實現了Servlet規範,可以執行我們自己編寫的Servlet應用程式處理動態請求,並返回響應,下面介紹Listener、Filter、Servlet、Request、Respones這幾個比較常見的物件元素。
1、Listener
Listener(監聽器)用來監聽一些物件的事件,當事件發生時可以進入到定義監聽器中進行處理,主要有ServletContextListener、HttpSessionListener 和 ServletRequestListener。
我們程式中可以實現這些JavaEE Servlet API中提供的監聽器介面,然後通過web.xml定義部署發生作用,如ServletContextListenerServlet(Servlet 上下文事件監聽器)介面可以監聽到部署web應用Servlet的狀態改變通知(如建立、關閉),如Spring框架中常見的一些ServletContextListenerServlet實現在web.xml定義如下:
它們都實現javax.servlet.ServletContextListener介面,如org.springframework.web.context.ContextLoaderListener用來在部署相關Web應用時初始化其上下文環境,在停止退出Web應用時清理其資源,如下:
Servlet容器需要在開始執行進入應用的第一個請求之前完成Web應用中的監聽器類的例項化,而且保持每一個監聽器的引用直到為Web應用最後一個請求提供服務。
更多Listener資訊請參考:《Servlet3.1規範(最終版)》第10章
2、Filter
Filter(過濾器)可以改變HTTP請求的內容、響應、及header資訊,過濾器通常不產生響應或像 servlet 那樣對請求作出響應,而是修改或調整到資源的請求,修改或調整來自資源的響應。
Filter在部署描述符中通過<filter>元素宣告,一個過濾器或一組過濾器可以通過在部署描述符中定義<filter-mapping>來為呼叫配置。
容器部署Web應用時,必須確保它為過濾器列表中的每一個都例項化了一個適當類的過濾器, 並呼叫其Filter.init()方法;當容器接收到傳入的請求時,它將獲取列表中所有符合該請求的過慮器組成過慮器鏈(FilterChain),然後通過FilterChain巢狀呼叫各過慮器的Filter.doFilter()方法(一個過濾器可以使得濾器鏈呼叫下一個過濾器),傳入ServletRequest 和ServletResponse進行處理。
當濾器鏈呼叫完各Filter.doFilter()方法後,會呼叫相關Servlet.service()方法,從而進行Servlet的處理。注意,Filter.doFilter()可以阻止過濾器連結下來的呼叫,返回時過濾器負責填充Reponse物件。
過濾器例項移除之前,容器必須先呼叫過濾器的Filter.destroy()方法。
如Struts2框架通過在web.xml中定義其實現了Filter介面的StrutsPrepareAndExecuteFilter來作為處理請求的入口,如下:
StrutsPrepareAndExecuteFilter.init()在部署Web應用時被容器呼叫,其實現了Struts2配置檔案的讀取及初始化,而在doFilter()方法中找到符合的Action處理程式後,就不再呼叫chain.doFilter(),而經Action處理後開始返回,如下:
更多Filter資訊請參考:《Servlet3.1規範(最終版)》第6章
3、Servlet
Servlet 這裡指的是實現了javax.servlet.Servlet介面的處理程式,一般開發中都是繼承HttpServlet,其繼承自實現了Servlet介面的GenericServlet類。
容器在部署Web應用程式時,或Servlet第一次請求處理時例項化呼叫Servlet.init()方法;而Servlet.service()方法從上面Filter介紹中可以知道是在各Filter.doFilter()巢狀呼叫中被呼叫的,而HttpServlet..service()中會根據請求型別分為doGet(),doPost()等方法,繼承HttpServlet只需重寫這樣些需要的方法即可,如Tomcat的/conf/web.xml定義了預設的DefaultServlet用來處理靜態內容請求(如html/js/各種圖片),如下:
而當Servlet容器確定servlet應該從服務中移除時(記憶體不足等),將呼叫Servlet.destroy()方法以允許Servlet釋放它使用的任何資源和儲存任何持久化的狀態。
容器中的Servlet例項通常都是單例的(可通過實現SingleThreadModel 介面實現每個請求對應一個Servlet),所以需要注意在多執行緒下的執行緒安全問題。
更多Servlet資訊請參考:《Servlet3.1規範(最終版)》第2章
4、Request與Response
Request和Response都可以在上面這些處理介面程式中通過引數接收到,Request物件封裝了客戶端請求的所有資訊,Response物件封裝了從伺服器返回到客戶端的所有資訊。
每個Request/Response物件只在Servlet.service()方法、或Filter.doFilter()方法的作用域內有效;發生非同步處理的情況下,物件一直有效,直到呼叫AsyncContext.complete()方法。
除了非同步請求時的AsyncContext.startAsync()和AsyncContext.complete()方法,Request/Response物件的實現都不保證執行緒安全,多執行緒訪問時需要同步處理。
更多資訊請參考:《Servlet3.1規範(最終版)》
2、web.xml檔案說明
上篇檔案章介紹過web.xml是Web應用程式部署描述符檔案web.xml,描述組成應用程式的servlet和其他元件、以及相關初始化引數等資訊。
web.xml中元件載入順序為:
context-param -> listener -> filter -> servlet(同類則按編寫順序執行)。
web.xml常用元件解析:
[plain] view plain copy
- <span style="color:#000000;"><web-app>
- <display-name></display-name> <!--WEB應用的名字 -->
- <description></description> <!--WEB應用的描述-->
- <context-param></context-param> <!--context-param元素宣告應用範圍內的初始化引數-->
- <!--例如指定spring載入多個spring配置檔案-->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml
- </param-value>
- </context-param>
- <<strong>filter></filter></strong> <!--過濾器將一個名字與一個實現javax.servlet.Filter介面的類相關聯-->
- <strong><filter-mapping></filter-mapping> <</strong>!--一旦命名了一個過濾器,就要利用filter-mapping元素把它與一個或多個servlet或JSP頁面相關聯-->
- <strong><listener></listener></strong> <!--事件監聽程式在建立、修改和刪除會話或servlet環境時得到通知。Listener元素指出事件監聽程式類,如Log4j這個廣泛使用的監聽器-->
- <strong><servlet></servlet></strong> <!--在向servlet或JSP頁面制定初始化引數或定製URL時,必須首先命名servlet或JSP頁面。Servlet元素就是用來完成此項任務的。-->
- <strong><servlet-mapping></servlet-mapping> </strong><!--伺服器一般為servlet提供一個預設的URL:http://host/webAppPrefix/servlet/ServletName,但是,常常會更改這個URL,以便servlet可以訪問初始化引數或更容易地處理相對URL。在更改預設URL時,使用servlet-mapping元素-->
- <session-config></session-config> <!--如果某個會話在一定時間內未被訪問,伺服器可以拋棄它以節省記憶體,可通過使用HttpSession的setMaxInactiveInterval方法明確設定單個會話物件的超時值,或者可利用session-config元素制定預設超時值-->
- <mime-mapping></mime-mapping> <!--如果Web應用具有想到特殊的檔案,希望能保證給他們分配特定的MIME型別,則mime-mapping元素提供這種保證-->
- <welcome-file-list></welcome-file-list> <!--指示伺服器在收到引用一個目錄名而不是檔名的URL時,使用哪個檔案(其實就是歡迎介面或者說入口介面一般為index.*) -->
- <error-page></error-page> <!--在返回特定HTTP狀態程式碼時,或者特定型別的異常被丟擲時,能夠制定將要顯示的頁面-->
- <taglib></taglib> <!--對標記庫描述符檔案(Tag Libraryu Descriptor file)指定別名。此功能使你能夠更改TLD檔案的位置, 而不用編輯使用這些檔案的JSP頁面-->
- <resource-env-ref></resource-env-ref> <!--宣告與資源相關的一個管理物件-->
- <resource-ref></resource-ref> <!--宣告一個資源工廠使用的外部資源-->
- <security-constraint></security-constraint> <!--制定應該保護的URL。它與login-config元素聯合使用-->
- <login-config></login-config> <!--指定伺服器應該怎樣給試圖訪問受保護頁面的使用者授權,它與sercurity-constraint元素聯合使用-->
- security-role></security-role> <!--給出安全形色的一個列表,這些角色將出現在servlet元素內的security-role-ref元素的role-name子元素中。分別地宣告角色可使高階IDE處理安全資訊更為容易-->
- <env-entry></env-entry> <!--宣告Web應用的環境項-->
- </web-app></span>
更多部署檔案資訊請參考:《Servlet3.1規範(最終版)》第14章
另外從Servlet3.0開始可以支援一些註釋直接在程式碼中進行定義部署,如下圖中,並不需要web.xml也能執行該Servlet:
3、Tomcat一些實現細節
上面大體瞭解Servlet技術與web.xml,下面來了解Tomcat的一些具體實現細節,從一些關注點入手:Tomcat的啟動/初始化配置、Tomcat如何實現Servlet容器--處理請求並響應等。
下面是以Tomcat 8.5.9版本原始碼除錯分析,不同版本可能有差異;另外,圖片看不清可以另外開啟檢視。
3-1、Tomcat啟動/初始化
3-1-1、catclina.shstart命令啟動
Tomcat的專案工程名稱也稱為"catclina",啟動是通常是通過"catclina.sh start"指令碼命令(start.sh也是呼叫該命令),呼叫了JDK中的Java虛擬機器來執行"org.apache.catalina.startup.Bootstrap"的main()方法入口,指令碼內容如下:
3-1-2、設定類載入器/Tomcat的類載入器架構
先是Bootstrap.initClassLoaders()設定類載入器:CommonClassLoader 、ServerClassLoader 、SharedClassLoader,分別對應的載入目錄為(根目錄下):/common(存放Tomcat與所有Web應用程式共用的類庫)、/server(只Tomcat使用、而所有Web應用程式不可見的)、/shared(Tomcat不可見、而所有Web應用程式共用)。
這是通過/conf/catalina.properties設定,預設只為設定了CommonLoader,所以只會建立CommonLoader,而Server.loader 、SharedLoader都使用CommonLoader,而對應的三個目錄合併為/lib(這是Tomcat6的簡化改進)。
另外,在後面初始化每個Web應用程式解析web.xml時,會建立WebappClassLoader,只有對應的Web應用程式可見,載入對應Web應用程式的/WEB-INF/lib裡的類庫。
所以預設情況下,Tomcat類載入器架構如下:
其中Bootstrap類載入器為Java虛擬機器提供,包含JDK基本執行時類,而System類載入器用於Tomcat啟動初始化(通常忽略);另外,Tomcat類載入器架構是按照經典的"雙親委派模型"來實現的,即:當類載入器被要求載入特定的類或資源時,它首先將請求委託給父類載入器,然後只有當父類載入器找不到請求的類或資源時,它才在自己的儲存庫中查詢。
Tomcat的類載入器架構的好處是可以按需要實現Tomcat與Web應用程式、以及不現Web應用程式之間的類庫共享與隔離,如常用的Spring等類庫可以放到共享目錄,為多個Web應用程式共用;而"雙親委派模型"也是JDK類載入器的架構,可以有效組織類庫的層次結構,避免一個類被不同載入器載入多次(注意,同一個類檔案被不同載入器載入表示不同的類)。
更多JVM類載入器資訊請參考:《Java虛擬機器規範》第5章 載入、連結與初始化
更多Tomcat類載入器資訊請參考:Tomcat Doc《Class Loader HOW-TO》
3-1-3、解析server.xml,建立各Tomcat元件
如圖,Catalina.load()中建立Diegster例項後,用該例項解析Tomcat的核心配置檔案server.xml,然後根據server.xml檔案中的配置規則開始建立各個元件,如Server、Connector等等,原始碼中主要過程如下:
建立Connector是根據配置的協議找到對應的處理器類名,然後通過反射來建立該處理器,如下:
3-1-4、初始化各Tomcat元件
各元件建立後,Catalina.load()中呼叫Server元件的初始化函式,Server.initInternal()又呼叫內部包含的Service元件的初始化…以此類推,按配置檔案的元件結構順序初始化,如Http型別的Connector元件初始化會對其ServerSocket進行繫結,原始碼過程如下:
3-1-5、啟動各Tomcat元件
上圖只展示了開始的一部分過程,同上面初始化一樣,是按照各元件在配置檔案中的組織結構來啟動,從Catalina.start()開始,而在Service中分別啟動Engine和Connector,還需要注意的是MapperLinstener.start()的處理,如下:
(1)、Engine.start()--部署Web應用程式
(A)、啟動部署,建立Context元件
其中Engine.startInternal()會為每個Host建立一個部署執行緒,Host在部署執行緒中呼叫HostConfig.deployApps()部署三種定義的Web應用程式,如下:
同樣,如果發現需要部署的Web應用程式,會為每個Web應用程式建立一個單獨的部署執行緒,然後在該執行緒中建立相應的Context元件,並在Context.startInternal()中建立相應的WebApp類載入器,如下:
(B)、解析web.xml
而後開始在ContextConfig.webConfig()中解析web.xml部署描述檔案,在ContextConfig.configureContext(WebXml webxml)根據解析web.xml的資訊建立封裝各種應用元素,如Filter、Servlet、Session等等,其中Servlet被封裝成Wrapper,加入到相應的Context元件中,如下:
(C)、Servlet.init()初始化
接下來就是Servlet例項初始化,Servlet規範中定義可以通過"load-on-startup"引數來指定,不小於0的整數時載入後呼叫Servlet.init(),定義多個Servlet時越大越先初始化;而小於0或沒定義該引數時由容器實現來定義,Tomcat中除JspServlet外,其他的Servlet型別是在第一次使用處理請求時再呼叫Servlet.init(),/conf/web.xml檔案中預設的兩個Servlet都定義了"load-on-startup"引數大於0,在載入後呼叫Servlet.init(),如下:
DefaultServlet.init()呼叫過程如下:
而處理請求時呼叫的Servlet.init()過程如下:
(D)、Web應用程式變化監控
Host部署完成全部的Web應用程式後,退回到main執行緒,建立一個後臺執行緒,在Engine容器的生命週期中每隔10秒會監控檢查各Web應用程式內容(war檔案的時間戳、context.xml、web.xml)是否已更改,如果改變會自動重新載入,建立過程如下:
(2)、MapperListener.start()—建立URL對映關係
解析完web.xml得到封裝相關資訊的各物件後,通過MapperListener建立配置的URL對映關係,即儲存到Service中的一個"org.apache.catalina.mapper.Mapper"例項裡,主要是Host、Contex、 Wrappers(Servlet)與對應的URL的對映關係,當處理使用者請求時,可以很方便的通過請求URL從該Mapper例項中找到對應的Host、Contex、 Wrappers(Servlet)來處理。
建立對映關係的主要過程如下:
(3)、Connect.start()—建立併發執行緒模型
前面說到了Connector和相應處理器的建立,而Connect.start()主要是建立併發執行緒模型來接收處理請求,下面以預設的Http/1.1 NIO型別的Connector為例說明,它會建立四種類型的執行緒:Worker執行緒、Poller執行緒、Acceptor執行緒、AsyncTimeout執行緒,前三種整體建立過程如下:
(A)、建立Work執行緒
Work(工作)/exec執行緒用來處理請求連線,先根據配置引數建立Work執行緒池,執行緒池最小和最大執行緒數量可以通過"minSpareThreads"和"maxThreads"設定,預設為最小10和最大200,而執行緒空閒時間預設為60s後關閉,原始碼中建立過程如下:
(B)、建立Poller執行緒,並啟動
說到Poller(輪詢)執行緒就得提下Java NIO,通過Selector來實現Socket I/O多路複用模型:當Acceptor執行緒中ServerSocket.accept()監聽到一個新的請求連線時,會把表示該請求連線的Socket註冊到Poller執行緒的Selector中,Selector可以阻塞監聽多個請求連線的Socket,當其中有Socket發生監聽事件(如請求資料到來)時會退出阻塞狀態,然後把發生請求資料事件的Socket交給Work執行緒處理。
而Poller(輪詢)執行緒用來輪詢Selector,這樣的好處就是:在沒有請求資料時,只有極少數的Poller執行緒阻塞,而避免了直接使用多個Work執行緒阻塞的消耗。
建立過程如(5-2)中的圖,其中Poller執行緒數量可以通過引數"pollerThreadCount"設定,預設值為每個處理器1個,但不超過2個,當大量的傳送檔案操作正在進行時,增加該值也可能是有益的。
關於更多的I/O模型資訊請參考:《5種IO模型、阻塞IO和非阻塞IO、同步IO和非同步IO》
(C)、建立Acceptor執行緒,並啟動
上面說到Acceptor執行緒用來呼叫ServerSocket.accept()(8080埠)阻塞監聽到使用者新的請求連線,建立過程如下:
(D)、建立AsyncTimeout執行緒,並啟動
AsyncTimeout執行緒是用來實現非同步請求的超時,建立過程如下:
關於Http/1.1 NIO型別的Connector建立完成後如下圖(選中執行緒,而Work執行緒在接收請求資料時建立):
3-2、Tomcat請求處理過程
上面介紹了Tomcat的啟動過程,主要初始化了各元件、Servlet,以及建立4種類型執行緒的併發模型,其中Work線在接收請求資料時再來建立。
下面還是以HTTP NIO型別的Connector為例,先介紹各型別執行緒間具體是如何接收請求的,再先來介紹請求處理過程。
3-2-1、各型別執行緒間接收請求/併發模型
1、Acceptor執行緒接收請求,建立連線Socket
在瀏覽器中訪問Tomcat預設ROOT應用下的tomcat.png ,URL為:http://localhost:8080/tomcat.png;然後Acceptor執行緒中ServerSocket.accept()就會監聽到這個新的請求連線,返回一個代表該請求連線的socket,如下:
2、連線Socket註冊到Poller執行緒Selector進行監聽
然後為該Socke建立一個NIO Channel(通道),該通道有許多特性,操作Socket是通過該通道進行的;然後把該通道註冊到其中的一個Poller執行緒(這裡是Poller1)的Selector多路複用器中,如下:
3、Selector監聽到資料,建立/交給Work(Exec)執行緒處理
如上圖,NioEndpoint.Poller.register()註冊函式裡會插入一個"OP_READ"操作(Key),這使得Poller執行緒中的Selector返回該Key進行處理,然後Poller執行緒中先建立一個SocketProcessor處理器,然後再通過執行緒池建立Work(Exec)執行緒並啟動處理來該Socket,如下:
3-2-2、請求處理過程
上面說到了請求如何傳遞到Work(Exec)執行緒的,下面主要介紹在Work執行緒執行SocketProcessor來處理來該Socket,整體過程如下:
1、提取請求資訊到Request物件,找到URI對映關係
先是建立一個Http11Processor,再用該處理器來處理,如下
同樣 Http11Processor和CoyoteAdapter主要是都提取請求資訊,封裝到Request物件,後面的處理都是通過Request物件來處理,而後通過Response物件返回響應。
其中需要注意的是,CoyoteAdapter.postParseRequest()方法中會通過前面介紹Tomcat啟動時儲存Host、Context、Wapper(Servlet)對映關係的Mapper例項,找到該URL請求對應的Host、Context、Wapper(Servlet),並儲存到Request物件的MappingData成員物件中,如下:
2、Tomcat元件對請求的處理
之後就是通過該Request物件的MappingData找到相應的一系列元件來處理的過程,整個過程都是以責任鏈模式來處理的。
3、Filter過慮器對請求處理
接下主要關注StandardWrapper中Servlet的處理,先為該Servlet建立一個FilterChain,並把Web.xml中定義的對該Servlet匹配的Filter(過慮器)加入到該FilterChain,如下:
這是就是FilterChain.doFilter()呼叫Filter.doFilter()來處理請求(),在每個Filter.doFilter()又會呼叫FilterChain.doFilter(),這樣以責任鏈的模式不斷巢狀呼叫,直到FilterChain.doFilter()發現所有Filter都呼叫完成,再呼叫Servlet的處理函式servlet.service()。
4、Servlet程式對請求處理,返回靜態資源
如請求中會有一個WsFilter過濾器,然後呼叫到預設的DefaultServlet,過程如下:
預設的DefaultServlet用來處理靜態內容請求(如html/js/各種圖片),由於繼承自JavaEE中的HttpServlet,所以HttpServlet.service()中會根據GET請求型別呼叫到DefaultServlet中重寫的doGet()方法,該方法只調用例項自己的serveResource()方法,如下:
所以serveResource()方法是實現靜態資源請求處理的過程,如果請求資源不存在CacheEntry.exists為false,則返回404(SC_NOT_FOUND),如下:
如果客戶端存在快取,checkIfHeaders()會根據客戶端請求頭的If-None-Match,If-Modified-Since等,來判斷請求資源是否被修改,如果未被修改,則返回304頭,客戶端直接從客戶端快取中讀取資原始檔,如下:
否則,先設定一些Response Http頭的欄位,如contentType,而後讀取請求的圖片資料,如下:
最後返回,釋放相關資源,可以看到請求圖片如下:
相關推薦
Tomcat(二) Tomcat實現: Servlet與web.xml介紹 以及 原始碼分析Tomcat實現細節
轉載自;http://blog.csdn.net/tjiyu/article/details/54590259 -------如有侵權 請聯絡我 我會進行刪除 在《Tomcat(一
Tomcat(二) Tomcat實現:Servlet與web.xml介紹 以及 原始碼分析Tomcat實現細節
<web-app> <display-name></display-name> <!--WEB應用的名字 --> <description></description> <!--WEB應用的描述--&
Servlet 3.0註解與web.xml配置引發的tomcat啟動報錯
Caused by: java.lang.IllegalArgumentException: The servlets named [FindWordServlet] and [com.heima.servlet.FindWordServlet] are both mapped to the
配置servlet的web.xml檔案導致tomcat無法啟動
我們按正常步驟建立servlet,接著配置web.xml檔案,然後我們啟動伺服器時發現提示如下錯誤: 提示Tomcat伺服器遇到一個問題,那我們首先看一下java檔案: 我們可以發現在13行處:@WebServlet("/HelloWorld") 接下來看一下x
各種容器與伺服器的區別與聯絡:Servlet容器 WEB容器 Java EE容器 應用伺服器 WEB伺服器 Java EE伺服器
各種容器與伺服器的區別與聯絡 Servlet容器 WEB容器 Java EE容器 應用伺服器 WEB伺服器 Java EE伺服器 平時我們經常看到各種容器名稱:Servlet容器、WEB容器、Java WEB容器、Java EE容器等,還有各種伺服
Servlet基礎(二):Servlet與JSP
詳情請檢視個人部落格Servlet基礎(二) JSP是一種指令碼語言,包裝了Java Servlet系統的介面,簡化了Java和Servlet的使用難度,同時通過擴充套件JSP標籤(TAG)提供
思科二層以太網與三層以太網技術的實現與區別
路由交換 以太信道 思科 1、打開 pt 7.0 將所需設備拖出來,用連接線纜將相關的端口連接好。試驗用g0/1,g0/2口2、接下來,先易後難,配置二層交換機以太網port-channel,進配置模式命名交換機,進相關端口配置通道協議和模式。兩臺交換機配置一樣附上配置命令:交換機1sw1(con
通證經濟大局觀(二十三):部落與技術進步
既然我們是以組織和協作模式的角度來聊通證經濟體,且丟擲了一個大結論:通證經濟體將超越公司和國家,成為歷史的必然。那麼,就有必要循著人類組織和協作模式的演化長河,溯流而下,試看“通證經濟體”是否沿途必經的高山峽谷。 在大自然的進化中,有兩種方向,一種是個體越來越強,比如老虎的凶猛、豹子的速度、老鷹
JsonUtils的實現:物件與json相互轉換
pom.xml依賴 <dependency> <groupId>com.fasterxml.jackson.core</groupId> &
spring boot 用war包部署到tomcat下詳細教程(解決缺少web.xml報錯的問題)
1.首先 修改pom.xml下的打包方式 <packaging>war</packaging> 2.新增servlet-api依賴 <!--新增servlet-api的依賴--> <dependency> <gr
tensorflow學習筆記(二十三):variable與get_variable
Variable tensorflow中有兩個關於variable的op,tf.Variable()與tf.get_variable()下面介紹這兩個的區別 tf.Variable與tf.get_variable() tf.Variable(ini
Java核心程式設計十四:Applet與Web
1 Applet基礎 1.1 Applet簡介 Applet是一種將Java程式,通常為UI程式載入進web瀏覽器,在使用者的瀏覽器中執行的一套轉換機制。因而HTML頁面中必須支援相關的標籤,告訴瀏覽器下載哪些類檔案,以及如何在網頁上進行顯示的資訊。如果一切就緒,則由瀏覽器
Tomcat啟動時載入資料到快取[web.xml中listener載入順序]
最近用到在Tomcat伺服器啟動時自動載入資料到快取,這就需要建立一個自定義的快取監聽器並實現ServletContextListener介面,並且在此自定義監聽器中需要用到Spring的依賴注入功能.在web.xml檔案中監聽器配置如下: <li
絕對路徑${pageContext.request.contextPath}用法及其與web.xml中Servlet的url-pattern匹配過程
以系統的一個“新增商品”的功能為例加以說明,系統頁面為add.jsp,如圖一所示: 圖一 新增商品介面 系統的程式碼目錄結構及add.jsp程式碼如圖二所示: 圖二 系統的程式碼目錄結構及add.jsp程式碼 ${pageContext.re
linux防火墻--firewalld:zone與service的介紹
service abc a13 備份 ffffff alt dff jpg 技術 iptables的備份與恢復 linux防火墻--firewalld firewalld的9個zone firewalld關於service的操作 小需求舉例 linux防火墻--fi
Spring與web.xml
之前 rac 靜態 req 監聽器 請求 jpg n) 文件 出處:http://blog.csdn.net/u010796790 在web.xml配置監聽器 ContextLoaderListener (listener-class) ContextLoaderList
c++模板超程式設計:std::invoke原始碼分析及其實現
在實現invoke之前,我們先看一下標準庫種invoke的使用方式 template< class F, class... Args>std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... ar
分散式學習筆記十三:分散式事務 TCC-Transaction 原始碼分析 —— TCC 實現
本文主要基於 TCC-Transaction 1.2.3.3 正式版 1. 概述 本文分享 TCC 實現。主要涉及如下三個 Maven 專案: tcc-transaction-core :tcc-transaction 底層實現。 tcc-transaction-ap
iOS探索:RunLoop本質、資料結構以及常駐執行緒實現
RunLoop的本質 RunLoop是通過內部維護的事件迴圈來對事件/訊息進行管理的一個物件 沒有訊息需要處理時,休眠以避免資源佔用,狀態切換是從使用者態通過系統呼叫切換到核心態 有訊息處理時,立刻被喚醒,狀態切換是從核心態通過系統呼叫切換到使用者態 這裡有一個問題,我們應用程式中
Struts2控制器以及struts.xml與web.xml的配置(1)
MVC設計模式MVC設計模式的宗旨是把一個Web應用的輸入、處理和輸出流程按照Model、View、和Controller的方式進行分離,這樣一個應用就被分成3個層:模型層、檢視層、和控制層。檢視(view):檢視代表使用者互動介面。MVC對於檢視的處理僅限於檢視中資料的採集