日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tomcat(12)org.apache.catalina.core.StandardContext源码剖析

發布時間:2023/12/3 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tomcat(12)org.apache.catalina.core.StandardContext源码剖析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【0】README 0)本文部分文字描述轉自 “how tomcat works”,旨在學習?“tomcat(12)StandardContext源碼剖析”?的基礎知識; 1)Context實例表示一個具體的web 應用程序,其中包含一個或多個Wrapper實例,每個Wrapper 表示一個具體的servlet定義; 2)Context容器還需要其他組件的支持,如載入器和Session 管理器。本章要intro 的 StandardContext是 catalina中Context接口的標準實現; 3)本文首先會回顧StandardContext類的實例化和配置,然后討論與其相關的StandardMapper類 和 ContextConfig類。接下來,學習對于引入的每個HTTP 請求的方法調用序列;
【1】StardardContext 配置 1)intro:創建了StandardContext實例后,必須調用其start() 方法來為引入的每個http 請求提供服務; 1.1)StandardContext對象可能啟動失敗:這時available 設置為false,該屬性表明StandardContext 對象是否可用; 1.2)若啟動成功:available=true,則表明StandardContext 對象配置正確; 2)正確配置StandardContext后,StandardContext才能讀入并解析默認的 web.xml文件,該文件位于 %CATALINA_HOME%/conf 目錄下,該文件的內容會應用到所有部署到tomcat 中的應用程序中。這也保證了StandardContext 實例可以處理應用程序級的web.xml 文件; 3)StandardContext.configured屬性:表明StandardContext 實例是否正確配置 3.1)StandardContext使用了一個事件監聽器作為其配置器;(干貨——StandardContext使用了一個事件監聽器作為其配置器,參見下圖中StandardContext.start()方法中lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null)?調用 3.2)當調用StandardContext.start()方法時,其中要做的一件事情是,觸發一個生命周期事件。該事件調用監聽器,對StandardContext實例進行配置; 3.3)若配置成功,則監聽器將 configured設置為true,否則StandardContext 實例拒絕啟動,也就無法為http 請求提供服務了; Attention)下面的圖片借用了 “tomcat(10)安全性中章節【6.4】中Supplement-補充模塊”的第1張圖;

【1.1】StandardContext 類的構造函數 1)源代碼如下: public StandardContext() { // org.apache.catalina.core.StandardContext.StandardContext().super();pipeline.setBasic(new StandardContextValve());namingResources.setContainer(this);} 2)構造函數最重要的事情:是為?StandardContext 實例的管道對象設置基礎閥;
【1.2】啟動StandardContext 實例 1)start()方法會初始化 StandardContext對象,用生命周期監聽器配置?StandardContext實例; 1.1)StandardContext 對象可能啟動失敗:這時available 設置為false,該屬性表明StandardContext 對象是否可用; 1.2)若啟動成功:available=true,則表明StandardContext 對象配置正確,與其關聯的子容器和組件都正確啟動; 2)正確配置后,StandardContext實例可以準備為引入的 http 請求提供服務了。若期間發生了錯誤,則available設置為false; 3)StandardContext.configured屬性:表明StandardContext 實例是否正確配置 3.1)在start()方法的末尾,?StandardContext實例會檢查 configured變量的值,若configured設置為 true,則StandardContext 啟動成功; 3.2)否則,調用stop() 方法,關閉在start() 方法已經啟動的所有組件; public synchronized void start() throws LifecycleException { //org.apache.catalina.core.StandardContext.start()方法if (started)throw new LifecycleException(sm.getString("containerBase.alreadyStarted", logName()));if (debug >= 1)log("Starting");// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);if (debug >= 1)log("Processing start(), current available=" + getAvailable());setAvailable(false);setConfigured(false);boolean ok = true;// Add missing components as necessaryif (webappResources == null) { // (1) Required by Loaderif (debug >= 1)log("Configuring default Resources");try {if ((docBase != null) && (docBase.endsWith(".war")))setResources(new WARDirContext());elsesetResources(new FileDirContext());} catch (IllegalArgumentException e) {log("Error initializing resources: " + e.getMessage());ok = false;}}if (ok) {if (!resourcesStart())ok = false;}// Install DefaultContext configurationif (!getOverride()) {Container host = getParent();if (host instanceof StandardHost) {((StandardHost)host).installDefaultContext(this);Container engine = host.getParent();if( engine instanceof StandardEngine ) {((StandardEngine)engine).installDefaultContext(this);}}}if (getLoader() == null) { // (2) Required by Managerif (getPrivileged()) {if (debug >= 1)log("Configuring privileged default Loader");setLoader(new WebappLoader(this.getClass().getClassLoader()));} else {if (debug >= 1)log("Configuring non-privileged default Loader");setLoader(new WebappLoader(getParentClassLoader()));}}if (getManager() == null) { // (3) After prerequisitesif (debug >= 1)log("Configuring default Manager");setManager(new StandardManager());}// Initialize character set mappergetCharsetMapper();// Post work directorypostWorkDirectory();// Reading the "catalina.useNaming" environment variableString useNamingProperty = System.getProperty("catalina.useNaming");if ((useNamingProperty != null)&& (useNamingProperty.equals("false"))) {useNaming = false;}if (ok && isUseNaming()) {if (namingContextListener == null) {namingContextListener = new NamingContextListener();namingContextListener.setDebug(getDebug());namingContextListener.setName(getNamingContextName());addLifecycleListener(namingContextListener);}}// Binding threadClassLoader oldCCL = bindThread();// Standard container startupif (debug >= 1)log("Processing standard container startup");if (ok) {try {addDefaultMapper(this.mapperClass);started = true;// Start our subordinate components, if anyif ((loader != null) && (loader instanceof Lifecycle))((Lifecycle) loader).start();if ((logger != null) && (logger instanceof Lifecycle))((Lifecycle) logger).start();// Unbinding threadunbindThread(oldCCL);// Binding threadoldCCL = bindThread();if ((cluster != null) && (cluster instanceof Lifecycle))((Lifecycle) cluster).start();if ((realm != null) && (realm instanceof Lifecycle))((Lifecycle) realm).start();if ((resources != null) && (resources instanceof Lifecycle))((Lifecycle) resources).start();// Start our Mappers, if anyMapper mappers[] = findMappers();for (int i = 0; i < mappers.length; i++) {if (mappers[i] instanceof Lifecycle)((Lifecycle) mappers[i]).start();}// Start our child containers, if anyContainer children[] = findChildren();for (int i = 0; i < children.length; i++) {if (children[i] instanceof Lifecycle)((Lifecycle) children[i]).start();}// Start the Valves in our pipeline (including the basic),// if anyif (pipeline instanceof Lifecycle)((Lifecycle) pipeline).start();// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(START_EVENT, null);if ((manager != null) && (manager instanceof Lifecycle))((Lifecycle) manager).start();} finally {// Unbinding threadunbindThread(oldCCL);}}if (!getConfigured())ok = false;// We put the resources into the servlet contextif (ok)getServletContext().setAttribute(Globals.RESOURCES_ATTR, getResources());// Binding threadoldCCL = bindThread();// Create context attributes that will be requiredif (ok) {if (debug >= 1)log("Posting standard context attributes");postWelcomeFiles();}// Configure and call application event listeners and filtersif (ok) {if (!listenerStart())ok = false;}if (ok) {if (!filterStart())ok = false;}// Unbinding threadunbindThread(oldCCL);// Set available status depending upon startup successif (ok) {if (debug >= 1)log("Starting completed");setAvailable(true);} else {log(sm.getString("standardContext.startFailed"));try {stop();} catch (Throwable t) {log(sm.getString("standardContext.startCleanup"), t);}setAvailable(false);throw new LifecycleException(sm.getString("standardContext.startFailed"));}// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);// Load and initialize all "load on startup" servletsoldCCL = bindThread();loadOnStartup(findChildren());unbindThread(oldCCL);} 對以上代碼的調用過程進行分析-start()方法需要完成以下工作(works): work1)觸發 BEFORE_START 事件; public synchronized void start() throws LifecycleException { //org.apache.catalina.core.StandardContext.start()方法。if (started)throw new LifecycleException(sm.getString("containerBase.alreadyStarted", logName()));if (debug >= 1)log("Starting");// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); work2)將 availability 屬性設置為false; work3)將 configured 屬性設置為 false; if (debug >= 1)log("Processing start(), current available=" + getAvailable());setAvailable(false);setConfigured(false);boolean ok = true; work4)配置資源; // Add missing components as necessaryif (webappResources == null) { // (1) Required by Loaderif (debug >= 1)log("Configuring default Resources");try {if ((docBase != null) && (docBase.endsWith(".war")))setResources(new WARDirContext());elsesetResources(new FileDirContext());} catch (IllegalArgumentException e) {log("Error initializing resources: " + e.getMessage());ok = false;}}if (ok) {if (!resourcesStart())ok = false;}// Install DefaultContext configurationif (!getOverride()) {Container host = getParent();if (host instanceof StandardHost) {((StandardHost)host).installDefaultContext(this);Container engine = host.getParent();if( engine instanceof StandardEngine ) {((StandardEngine)engine).installDefaultContext(this);}}} work5)設置載入器; if (getLoader() == null) { // (2) Required by Managerif (getPrivileged()) {if (debug >= 1)log("Configuring privileged default Loader");setLoader(new WebappLoader(this.getClass().getClassLoader()));} else {if (debug >= 1)log("Configuring non-privileged default Loader");setLoader(new WebappLoader(getParentClassLoader()));}} work6)設置Session 管理器; if (getManager() == null) { // (3) After prerequisitesif (debug >= 1)log("Configuring default Manager");setManager(new StandardManager());} work7)初始化字符集映射器; // Initialize character set mappergetCharsetMapper(); // defined in start().public CharsetMapper getCharsetMapper() {// Create a mapper the first time it is requestedif (this.charsetMapper == null) {try {Class clazz = Class.forName(charsetMapperClass);this.charsetMapper =(CharsetMapper) clazz.newInstance();} catch (Throwable t) {this.charsetMapper = new CharsetMapper();}}return (this.charsetMapper);} work8)啟動與該Context 容器相關聯的組件; // Post work directorypostWorkDirectory(); // Reading the "catalina.useNaming" environment variableString useNamingProperty = System.getProperty("catalina.useNaming");if ((useNamingProperty != null)&& (useNamingProperty.equals("false"))) {useNaming = false;}if (ok && isUseNaming()) {if (namingContextListener == null) {namingContextListener = new NamingContextListener();namingContextListener.setDebug(getDebug());namingContextListener.setName(getNamingContextName());addLifecycleListener(namingContextListener);}}// Binding threadClassLoader oldCCL = bindThread(); work9)啟動子容器; work10)啟動管道對象; work11)啟動Session 管理器;
work12)觸發 START 事件,在這里監聽器(ContextConfig 實例)會執行一些配置操作,若配置成功,ContextConfig 實例會將 StandardContext.configured 變量設置為 true; // Set available status depending upon startup successif (ok) {if (debug >= 1)log("Starting completed");setAvailable(true);} else {log(sm.getString("standardContext.startFailed"));try {stop();} catch (Throwable t) {log(sm.getString("standardContext.startCleanup"), t);}setAvailable(false);throw new LifecycleException(sm.getString("standardContext.startFailed"));} work13)檢查 configured 屬性的值,若為true,則調用 postWelcomePages()方法,載入那些需要在啟動時就載入的子容器,即 Wrapper實例,將 availability屬性設置為 true。若 configured 變量為false, 則調用stop() 方法; // Create context attributes that will be requiredif (ok) { // defined in start() method.if (debug >= 1)log("Posting standard context attributes");postWelcomeFiles();}private void postWelcomeFiles() {getServletContext().setAttribute("org.apache.catalina.WELCOME_FILES",welcomeFiles);} work14)觸發 AFTER_START 事件;? ? ? // Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); // highlight line.// Load and initialize all "load on startup" servletsoldCCL = bindThread();loadOnStartup(findChildren());unbindThread(oldCCL);
【1.3】 org.apahce.catalina.core.StandardContext.invoke() 方法 1)該方法首先會檢查應用程序是否正在重載過程中,若是,則等待應用程序重載完成。然后,它調用其父類的 ContainerBase.invoke() 方法; public void invoke(Request request, Response response) throws IOException, ServletException { // Wait if we are reloadingwhile (getPaused()) { // 返回 paused屬性的值,當paused為true時,表明應用程序正在重載;try {Thread.sleep(1000);} catch (InterruptedException e) {;}}// Normal request processingif (swallowOutput) {try {SystemLogHandler.startCapture();super.invoke(request, response);} finally {String log = SystemLogHandler.stopCapture();if (log != null && log.length() > 0) {log(log);}}} else {super.invoke(request, response);}} Attention)上述的StandardContext.invoke() 方法是tomcat 4中的實現,而在 tomcat5中,StandardContext 并沒有提供 invoke()方法的實現,所以會執行 ContainerBase.invoke() 方法;而檢查應用程序是否正在重載的工作移到了 StandardContextValve.invoke() 方法中;
【2】StandardContextMapper 類 1)對于每個引入的http 請求,都會調用 StandardContext實例的管道對象的基礎閥的invoke() 方法來處理;
1.1)StandardContext 實例的基礎閥:是 org.apache.catalina.core.StandardContextValve 類的實例; 1.2)StandardContextValve.invoke()方法要做的第一件事:是獲取一個要處理 http 請求 的Wrapper 實例; 2)在tomcat4中,StandardContextValve實例在它包含的?StandardContext中查找。StandardContextValve實例使用?StandardContext實例的映射器找到一個合適的 Wrapper實例。獲得Wrapper實例后,它就會調用 Wrapper.invoke()方法; 3)我們談談映射器: ContainerBase類是 StandardContext類的父類,前者定義 addDefaultMapper()方法用來添加一個默認的映射器,如下所示: protected void addDefaultMapper(String mapperClass) { // org.apache.catalina.core.ContainerBase.addDefaultMapper() method.// Do we need a default Mapper?if (mapperClass == null)return;if (mappers.size() >= 1)return;// Instantiate and add a default Mappertry {Class clazz = Class.forName(mapperClass);Mapper mapper = (Mapper) clazz.newInstance();mapper.setProtocol("http");addMapper(mapper);} catch (Exception e) {log(sm.getString("containerBase.addDefaultMapper", mapperClass),e);}} 3.2)StandardContext.start()方法中會調用 addDefaultMapper()方法,并傳入變量mapperClass的值: public synchronized void start() throws LifecycleException {// ......if (ok) {try {addDefaultMapper(this.mapperClass);started = true;} //...... // private String mapperClass = "org.apache.catalina.core.StandardContextMapper";
3.3)必須要調用映射器的setContainer()方法,通過傳入一個容器的實例,將映射器和容器相關聯。在Catalina中,org.apache.catalina.Mapper 接口的實現類是 org.apache.catalina.core.StandardContextMapper類 。StandardContextMapper實例只能與 Context級容器相關聯,setContainer()方法如下所示: public void setContainer(Container container) { // org.apche.catalina.core.StandardContextMapper.setContainer().if (!(container instanceof StandardContext))throw new IllegalArgumentException(sm.getString("httpContextMapper.container"));context = (StandardContext) container;}public StandardContext() { // 而在StandardContext構造中調用setContainer().super();pipeline.setBasic(new StandardContextValve());namingResources.setContainer(this);}
3.4)映射器最重要的方法是map()方法,該方法會返回用來處理http 請求的子容器,該方法簽名如下:? public Container map(Request request, boolean update) { // org.apache.catalina.core.StandardContextMapper.map().int debug = context.getDebug();// Has this request already been mapped?if (update && (request.getWrapper() != null))return (request.getWrapper());// Identify the context-relative URI to be mappedString contextPath =((HttpServletRequest) request.getRequest()).getContextPath();String requestURI = ((HttpRequest) request).getDecodedRequestURI();String relativeURI = requestURI.substring(contextPath.length());// Apply the standard request URI mapping rules from the specificationWrapper wrapper = null;String servletPath = relativeURI;String pathInfo = null;String name = null;// Rule 1 -- Exact Match // Rule 2 -- Prefix Match // Rule 3 -- Extension Match // Rule 4 -- Default Match // Update the Request (if requested) and return this Wrapper if ((debug >= 1) && (wrapper != null))context.log(" Mapped to servlet '" + wrapper.getName() +"' with servlet path '" + servletPath +"' and path info '" + pathInfo +"' and update=" + update);if (update) {request.setWrapper(wrapper);((HttpRequest) request).setServletPath(servletPath);((HttpRequest) request).setPathInfo(pathInfo);}return (wrapper);} } 4)現在,我們回到org.apche.catalina.core.StandardContextValve:其invoke()方法對于引入的每個http 請求,都會調用Context容器的map()方法,并傳入一個 org.apache.catalina.Request 對象。 public void invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException { <span style="font-family: Arial, Helvetica, sans-serif;">//org.apche.catalina.core.StandardContextValve.invoke().</span>// ..... // Disallow any direct access to resources under WEB-INF or META-INFHttpServletRequest hreq = (HttpServletRequest) request.getRequest();String contextPath = hreq.getContextPath();String requestURI = ((HttpRequest) request).getDecodedRequestURI();String relativeURI =requestURI.substring(contextPath.length()).toUpperCase();//......Context context = (Context) getContainer();Wrapper wrapper = null;try {wrapper = (Wrapper) context.map(request, true); // highlight line.->ContainerBase.map().} //......// Ask this Wrapper to process this Requestresponse.setContext(context);wrapper.invoke(request, response); } 4.1)map() 方法會針對某個特定的協議調用 findMapper()方法返回一個映射器對象,然后調用映射器對象的map() 方法獲取 Wrapper實例; public Container map(Request request, boolean update) {// Select the Mapper we will useMapper mapper = findMapper(request.getRequest().getProtocol());if (mapper == null)return (null);// Use this Mapper to perform this mappingreturn (mapper.map(request, update)); }public Mapper findMapper(String protocol) {if (mapper != null)return (mapper); // mapper == StandardContextMapperelsesynchronized (mappers) {return ((Mapper) mappers.get(protocol));}} 4.2)下面對org.apache.catalina.core.StandardContextMapper.map()方法的調用過程進行分析: step1)會先標識出相對于Context的URL: step2)然后,它試圖應用匹配規則找到一個適合的Wrapper實例;
Attention)以上代碼的都是基于tomcat4在做分析,而在tomcat5中,Mapper接口及其相關類已經被移除了。事實上,StandardContextValve.invoke()方法會從 request對象中獲取 適合的 Wrapper實例:?Wrapper wrapper = reqeust.getWrapper(); (該Wrapper實例指明了封裝在 request對象中的映射信息) // step1 begins. public Container map(Request request, boolean update) { // org.apache.catalina.core.StandardContextMapper.map().int debug = context.getDebug();// Has this request already been mapped?if (update && (request.getWrapper() != null))return (request.getWrapper());// Identify the context-relative URI to be mappedString contextPath =((HttpServletRequest) request.getRequest()).getContextPath();String requestURI = ((HttpRequest) request).getDecodedRequestURI();String relativeURI = requestURI.substring(contextPath.length());if (debug >= 1)context.log("Mapping contextPath='" + contextPath +"' with requestURI='" + requestURI +"' and relativeURI='" + relativeURI + "'"); // step1 ends. // step2 begins. // Apply the standard request URI mapping rules from the specificationWrapper wrapper = null;String servletPath = relativeURI;String pathInfo = null;String name = null;// Rule 1 -- Exact Matchif (wrapper == null) {if (debug >= 2)context.log(" Trying exact match");if (!(relativeURI.equals("/")))name = context.findServletMapping(relativeURI);if (name != null)wrapper = (Wrapper) context.findChild(name); //highlight line.if (wrapper != null) {servletPath = relativeURI;pathInfo = null;}}// Rule 2 -- Prefix Matchif (wrapper == null) {if (debug >= 2)context.log(" Trying prefix match");servletPath = relativeURI;while (true) {name = context.findServletMapping(servletPath + "/*");if (name != null)wrapper = (Wrapper) context.findChild(name); // highlight line.if (wrapper != null) {pathInfo = relativeURI.substring(servletPath.length());if (pathInfo.length() == 0)pathInfo = null;break;}int slash = servletPath.lastIndexOf('/');if (slash < 0)break;servletPath = servletPath.substring(0, slash);}}// Rule 3 -- Extension Matchif (wrapper == null) {if (debug >= 2)context.log(" Trying extension match");int slash = relativeURI.lastIndexOf('/');if (slash >= 0) {String last = relativeURI.substring(slash);int period = last.lastIndexOf('.');if (period >= 0) {String pattern = "*" + last.substring(period);name = context.findServletMapping(pattern); // highlight line.if (name != null)wrapper = (Wrapper) context.findChild(name);if (wrapper != null) {servletPath = relativeURI;pathInfo = null;}}}}// Rule 4 -- Default Matchif (wrapper == null) {if (debug >= 2)context.log(" Trying default match");name = context.findServletMapping("/");if (name != null)wrapper = (Wrapper) context.findChild(name); //highlight line.if (wrapper != null) {servletPath = relativeURI;pathInfo = null;}} // step2 ends. // step3 begins.// Update the Request (if requested) and return this Wrapperif ((debug >= 1) && (wrapper != null))context.log(" Mapped to servlet '" + wrapper.getName() +"' with servlet path '" + servletPath +"' and path info '" + pathInfo +"' and update=" + update);if (update) {request.setWrapper(wrapper);((HttpRequest) request).setServletPath(servletPath);((HttpRequest) request).setPathInfo(pathInfo);}return (wrapper);} 對以上代碼的分析(Analysis):以上代碼演示了通過 StandardContext.start()方法如何找到映射器和利用 URI 等信息來找到相應的Wrapper容器的;(Bootstrap.main() 設置了相應的child)
【3】對重載的支持 1)啟用重載功能:StandardContext.reloadable 屬性指明該應用程序是否 啟用了重載功能。當啟用了之后,當 web.xml 文件發生變化或 WEB-INF/classes 目錄下的其中一個文件被重新編譯后,應用程序會重載;
2)StandardContext是通過其載入器實現應用程序重載的: 在 tomcat4中,StandardContext對象中的 WebappLoader類實現了 Loader接口,并使用另一個線程檢查 WEB-INF 目錄中的所有類和JAR 文件的時間戳。只需要調用其 setContainer()方法將 WebappLoader 對象與?StandardContext 對象相關聯就可以啟動該檢查線程。
public synchronized void reload() { //org.apache.catalina.core.StandardContext.reload().// Validate our current component stateif (!started)throw new IllegalStateException(sm.getString("containerBase.notStarted", logName()));// Make sure reloading is enabled// if (!reloadable)// throw new IllegalStateException// (sm.getString("standardContext.notReloadable"));log(sm.getString("standardContext.reloadingStarted"));// Stop accepting requests temporarilysetPaused(true);// Binding threadClassLoader oldCCL = bindThread();// Shut down our session managerif ((manager != null) && (manager instanceof Lifecycle)) {try {((Lifecycle) manager).stop();} catch (LifecycleException e) {log(sm.getString("standardContext.stoppingManager"), e);}}// Shut down the current version of all active servletsContainer children[] = findChildren();for (int i = 0; i < children.length; i++) {Wrapper wrapper = (Wrapper) children[i];if (wrapper instanceof Lifecycle) {try {((Lifecycle) wrapper).stop();} catch (LifecycleException e) {log(sm.getString("standardContext.stoppingWrapper",wrapper.getName()),e);}}}// Shut down application event listenerslistenerStop();// Clear all application-originated servlet context attributesif (context != null)context.clearAttributes();// Shut down filtersfilterStop();if (isUseNaming()) {// StartnamingContextListener.lifecycleEvent(new LifecycleEvent(this, Lifecycle.STOP_EVENT));}// Binding threadunbindThread(oldCCL);// Shut down our application class loaderif ((loader != null) && (loader instanceof Lifecycle)) {try {((Lifecycle) loader).stop();} catch (LifecycleException e) {log(sm.getString("standardContext.stoppingLoader"), e);}}// Binding threadoldCCL = bindThread();// Restart our application class loaderif ((loader != null) && (loader instanceof Lifecycle)) {try {((Lifecycle) loader).start();} catch (LifecycleException e) {log(sm.getString("standardContext.startingLoader"), e);}}// Binding threadunbindThread(oldCCL);// Create and register the associated naming context, if internal// naming is usedboolean ok = true;if (isUseNaming()) {// StartnamingContextListener.lifecycleEvent(new LifecycleEvent(this, Lifecycle.START_EVENT));}// Binding threadoldCCL = bindThread();// Restart our application event listeners and filtersif (ok) {if (!listenerStart()) {log(sm.getString("standardContext.listenerStartFailed"));ok = false;}}if (ok) {if (!filterStart()) {log(sm.getString("standardContext.filterStartFailed"));ok = false;}}// Restore the "Welcome Files" and "Resources" context attributespostResources();postWelcomeFiles();// Restart our currently defined servletsfor (int i = 0; i < children.length; i++) {if (!ok)break;Wrapper wrapper = (Wrapper) children[i];if (wrapper instanceof Lifecycle) {try {((Lifecycle) wrapper).start();} catch (LifecycleException e) {log(sm.getString("standardContext.startingWrapper",wrapper.getName()),e);ok = false;}}}// Reinitialize all load on startup servletsloadOnStartup(children);// Restart our session manager (AFTER naming context recreated/bound)if ((manager != null) && (manager instanceof Lifecycle)) {try {((Lifecycle) manager).start();} catch (LifecycleException e) {log(sm.getString("standardContext.startingManager"), e);}}// Unbinding threadunbindThread(oldCCL);// Start accepting requests againif (ok) {log(sm.getString("standardContext.reloadingCompleted"));} else {setAvailable(false);log(sm.getString("standardContext.reloadingFailed"));}setPaused(false);// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(Context.RELOAD_EVENT, null);} 3)WebappLoader.setContainer()方法的實現代碼如下: public void setContainer(Container container) { // org.apache.catalina.loader.WebappLoader.setContainer().// Deregister from the old Container (if any)if ((this.container != null) && (this.container instanceof Context))((Context) this.container).removePropertyChangeListener(this);// Process this property changeContainer oldContainer = this.container;this.container = container;support.firePropertyChange("container", oldContainer, this.container);// Register with the new Container (if any)if ((this.container != null) && (this.container instanceof Context)) {setReloadable( ((Context) this.container).getReloadable() );((Context) this.container).addPropertyChangeListener(this);}} 對上述代碼的分析(Analysis):看上述代碼的 最后一個if語句塊:如果當前容器是 Context容器,則調用 setRealoadable()方法。這說明,WebappLoader.reloadable 屬性的值與 StandardContext.reloadable 屬性的值相同;
4)下面是 WebappLoader.setReloadable() 方法的實現代碼: public void setReloadable(boolean reloadable) { // org.apache.catalina.loader.WebappLoader.setContainer(). setReloadable()// Process this property changeboolean oldReloadable = this.reloadable;this.reloadable = reloadable;support.firePropertyChange("reloadable",new Boolean(oldReloadable),new Boolean(this.reloadable));// Start or stop our background thread if requiredif (!started)return;if (!oldReloadable && this.reloadable)threadStart();else if (oldReloadable && !this.reloadable)threadStop();} 對上述代碼的分析(Analysis): A1)若 reloadable 從false 修改為true:則會調用 threadStart()方法;而threadStart()方法會啟動一個專用的線程來不斷地檢查 WEB-INF 目錄下的類和 JAR 文件的時間戳; A2)若reloadable 從 true 修改為false:則調用調用 threadStop() 方法;而threadStop() 方法則會終止該線程; Attention)在tomcat5中,為支持重載功能而進行的檢查類的時間戳的工作改由 backgroundProcess()方法執行;
【4】backgroundProcess()方法 1)Context容器的運行需要其他組件的支持,例如載入器和Session 管理器。通常來說,這些組件需要使用各自的線程執行一些后臺處理程序; 2)為了節省資源,在tomcat5中, 使用了不同的方法。所有的后臺處理共享同一個線程。若某個組件 或 servlet容器需要周期性地執行一個操作,只需要將代碼寫到其 backgroundProcess()方法中即可;(干貨——tomcat5中,所有的后臺處理共享同一個線程。 3)這個共享線程在 ContainerBase對象中創建。ContainerBase.start()方法調用其 threadStart()方法啟動該后臺線程;(Attention-這是tomcat5中的 ContainerBase.start()) public synchronized void start() throws LifecycleException { //org.apache.catalina.core.ContainerBase.start() in tomcat5.// Validate and update our current component stateif (started) {log.info(sm.getString("containerBase.alreadyStarted", logName()));return;} // Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);started = true;// Start our subordinate components, if anyif ((loader != null) && (loader instanceof Lifecycle))((Lifecycle) loader).start();getLogger();if ((logger != null) && (logger instanceof Lifecycle))((Lifecycle) logger).start();if ((manager != null) && (manager instanceof Lifecycle))((Lifecycle) manager).start();if ((cluster != null) && (cluster instanceof Lifecycle))((Lifecycle) cluster).start();if ((realm != null) && (realm instanceof Lifecycle))((Lifecycle) realm).start();if ((resources != null) && (resources instanceof Lifecycle))((Lifecycle) resources).start();// Start our child containers, if anyContainer children[] = findChildren();for (int i = 0; i < children.length; i++) {if (children[i] instanceof Lifecycle)((Lifecycle) children[i]).start();}// Start the Valves in our pipeline (including the basic), if anyif (pipeline instanceof Lifecycle)((Lifecycle) pipeline).start();// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(START_EVENT, null);// Start our threadthreadStart(); //highlight line.// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);}protected void threadStart() { //org.apache.catalina.core.ContainerBase.threadStart() in tomcat5.if (thread != null)return;if (backgroundProcessorDelay <= 0)return;threadDone = false;String threadName = "ContainerBackgroundProcessor[" + toString() + "]";thread = new Thread(new ContainerBackgroundProcessor(), threadName); //highlight line.thread.setDaemon(true);thread.start();} 4)threadStart()方法:通過傳入一個實現了 java.lang.Runnable接口的 ContainerBackgroundProcessor 類的實例構造一個新線程。其ContainerBackgroundProcessor定義如下: protected class ContainerBackgroundProcessor implements Runnable { //org.apache.catalina.core.ContainerBase.ContainerBackroundProcessor class defined in tomcat 5, which is a inner class in ContainerBasepublic void run() {while (!threadDone) {try {Thread.sleep(backgroundProcessorDelay * 1000L);} catch (InterruptedException e) {;}if (!threadDone) {Container parent = (Container) getMappingObject();ClassLoader cl = Thread.currentThread().getContextClassLoader();if (parent.getLoader() != null) {cl = parent.getLoader().getClassLoader();}processChildren(parent, cl); // highlight line.}}}protected void processChildren(Container container, ClassLoader cl) {try {if (container.getLoader() != null) {Thread.currentThread().setContextClassLoader(container.getLoader().getClassLoader());}container.backgroundProcess(); // highlight line.} catch (Throwable t) {log.error("Exception invoking periodic operation: ", t);} finally {Thread.currentThread().setContextClassLoader(cl);}Container[] children = container.findChildren();for (int i = 0; i < children.length; i++) {if (children[i].getBackgroundProcessorDelay() <= 0) {processChildren(children[i], cl);}}}} 對以上代碼的分析(Analysis): A1)ContainerBackgroundProcessor?類:實際上是 ContainerBase類的內部類; A2)在其run()方法中是一個while 循環,周期性地調用其 processChildren()方法:而processChildren()方法會調用其自身對象的 backgroundProcess()方法 和其 每個子容器的 processChildren()方法; A3)通過實現backgroundProcess()方法,ContainerBase類的子類可以使用一個專用線程來執行周期性任務;

5)tomcat5 中 StandardContext.backgroundProcess()方法的實現如下:

public void backgroundProcess() { //org.apache.catalina.core.ContainerBase.backgroundProcess() in tomcat 5.if (!started)return;if (cluster != null) {try {cluster.backgroundProcess();} catch (Exception e) {log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e); }}if (loader != null) {try {loader.backgroundProcess();} catch (Exception e) {log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e); }}if (manager != null) {try {manager.backgroundProcess();} catch (Exception e) {log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e); }}if (realm != null) {try {realm.backgroundProcess();} catch (Exception e) {log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e); }}Valve current = pipeline.getFirst();while (current != null) {try {current.backgroundProcess();} catch (Exception e) {log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e); }current = current.getNext();}lifecycle.fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);}


總結

以上是生活随笔為你收集整理的tomcat(12)org.apache.catalina.core.StandardContext源码剖析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

五月天激情电影 | 97爱 | 日本在线观看中文字幕 | 国产精品99久久久久久久久久久久 | 亚洲欧洲精品一区二区精品久久久 | 欧美激情va永久在线播放 | 伊人视频 | 免费视频一区 | 天天操夜夜看 | 成年人免费av| 97国产超碰在线 | 欧美乱熟臀69xxxxxx | 人人搞人人干 | 国色天香永久免费 | 亚洲成色777777在线观看影院 | 五月婷婷一级片 | 日本三级不卡 | 久久爱资源网 | www.天天综合 | 五月黄色 | 色爱区综合激月婷婷 | 91最新国产 | 日本99久久| 亚洲精品视 | 青春草国产视频 | 亚洲精品字幕在线 | 国产一区二区在线精品 | 4438全国亚洲精品观看视频 | 亚洲欧美日韩精品久久奇米一区 | 丰满少妇一级片 | 韩国一区二区三区在线观看 | 成人免费观看视频网站 | 国内成人精品视频 | 久久一区二区免费视频 | 国产精品99久久久久久小说 | 自拍超碰在线 | 婷婷六月中文字幕 | 午夜精品久久久久久久99热影院 | 免费久久网| 日本女人的性生活视频 | 国模视频一区二区 | 国产日韩高清在线 | 精品国产一区在线观看 | 91久久偷偷做嫩草影院 | 国产又粗又猛又黄又爽的视频 | 天天干天天干天天射 | 色婷婷六月| 亚洲精欧美一区二区精品 | 欧美一二区在线 | 日韩成人免费在线 | 久久免费激情视频 | 日b视频在线观看网址 | 亚洲激情小视频 | 六月激情久久 | 免费看的黄色小视频 | 九九九九九九精品任你躁 | av高清网站在线观看 | 久久精品视频在线 | 伊色综合久久之综合久久 | 看片一区二区三区 | 久久超碰网 | 天天色天天骑天天射 | 亚洲国产一二三 | 国产99久久久国产精品成人免费 | 天天想夜夜操 | www.福利视频 | 免费看搞黄视频网站 | 六月色| 激情五月综合网 | 亚洲3级 | 欧美va天堂va视频va在线 | 国产成人av网站 | 日日操日日 | 91九色pron| 国产精品小视频网站 | 综合色综合 | 成人 亚洲 欧美 | 深夜免费小视频 | 5月丁香婷婷综合 | 国产黄色精品在线 | av高清在线观看 | 久久精品网站免费观看 | 一区二区精品在线视频 | 久草在线在线 | 中文字幕无吗 | 激情婷婷综合 | 97超视频 | 国产一级片在线播放 | 亚洲全部视频 | 在线视频电影 | 免费看黄电影 | 欧美在线视频二区 | 国产精品久久久久久久毛片 | 99热这里只有精品在线观看 | 欧美日韩在线免费观看 | 亚洲国产成人精品电影在线观看 | 免费高清在线观看电视网站 | 在线a人v观看视频 | 久久看免费视频 | 在线成人中文字幕 | 亚洲精品国产视频 | 色www免费视频 | 久久美女免费视频 | 九热在线| 国产福利在线免费 | 在线激情影院一区 | 97国产精品久久 | 久久乐九色婷婷综合色狠狠182 | 精品久久久久久亚洲综合网站 | 97色婷婷成人综合在线观看 | 欧美一区二区三区在线看 | 在线黄色国产 | 视频在线播放国产 | 欧美一级大片在线观看 | 人人爽人人搞 | 天天干天天操天天 | 精品国产一二三 | 婷婷久久精品 | 99视频免费在线观看 | 欧亚日韩精品一区二区在线 | 特及黄色片 | 久草在线视频在线观看 | 免费看一级一片 | 日本精品一区二区三区在线播放视频 | 免费在线播放av电影 | 黄网站色成年免费观看 | 福利视频一二区 | 日本二区三区在线 | 黄网站色视频 | 九九免费在线观看 | 成人h动漫精品一区二 | av在线一级 | 日韩精品免费一区 | 久久精品一区二区三区视频 | 亚欧日韩av | 免费看一级 | 天天色中文 | 黄色免费电影网站 | 欧美日韩一级视频 | 玖玖视频精品 | 四虎www.| 免费在线一区二区 | 久久人网| 国产午夜小视频 | 91av在线不卡 | 香蕉视频在线免费 | 丁香狠狠 | 国产日产欧美在线观看 | 亚洲日本va午夜在线电影 | 亚洲黄色免费网站 | 91精品推荐 | 超碰97人人射妻 | 日韩久久视频 | 中文字幕视频三区 | 亚洲欧美乱综合图片区小说区 | 二区视频在线观看 | 成+人+色综合 | 最近中文字幕国语免费高清6 | av电影av在线 | 九色精品| 麻豆视频免费入口 | 色婷婷国产精品一区在线观看 | 日韩av中文字幕在线 | 免费看一级| 国产精品岛国久久久久久久久红粉 | 国产成人综合图片 | 国内精品视频一区二区三区八戒 | 一区二区 不卡 | 91伊人影院 | 国产精品毛片一区 | 91九色视频导航 | 视频三区 | 91丨精品丨蝌蚪丨白丝jk | 亚洲精品一区二区18漫画 | 黄色成人影院 | 精品主播网红福利资源观看 | 色综合亚洲精品激情狠狠 | 在线视频 一区二区 | av电影在线观看完整版一区二区 | 日韩精品专区在线影院重磅 | 免费a现在观看 | 亚洲精品色视频 | 伊人色播 | 又黄又刺激的网站 | 欧美亚洲国产日韩 | 欧美一区二区精美视频 | 青青久草在线视频 | 人人狠狠| 激情偷乱人伦小说视频在线观看 | 黄色免费网站下载 | 国产一级特黄电影 | 国产91av视频在线观看 | 婷婷丁香九月 | 99亚洲精品 | 成人在线视频你懂的 | 天天插天天射 | 亚洲精品福利视频 | 成人免费毛片aaaaaa片 | 中文字幕免费一区二区 | 久草精品视频在线观看 | 国产在线精品一区二区 | 最新动作电影 | 韩国一区视频 | 免费日韩av片 | 又黄又爽又刺激视频 | 亚洲人成人天堂h久久 | 韩日电影在线 | 天天干天天综合 | 91精品视频一区二区三区 | 免费观看的黄色片 | 天天射天天射天天 | 国产成人精品一区二区三区在线观看 | 天天干夜夜夜操天 | 视频一区在线播放 | 国产精品久久久久久久毛片 | 亚洲涩涩一区 | 黄色精品在线看 | 日韩av手机在线观看 | 美女久久99 | 日日天天干 | 中文有码在线视频 | 一区二区在线不卡 | 久久99精品视频 | 青青河边草免费视频 | 视频 天天草| 麻豆视频在线免费观看 | 亚洲香蕉在线观看 | 91精品国产乱码在线观看 | 国产123av | 午夜精品久久久久久久久久久久 | 日韩www在线 | 91av在线国产 | 香蕉视频一级 | 久久国色夜色精品国产 | 国产九九精品视频 | 成人免费毛片aaaaaa片 | 成人av电影在线播放 | 麻豆免费在线播放 | 综合色影院 | 免费黄色一区 | 丁香六月婷婷综合 | 黄色综合 | 爱干视频 | 精品播放 | 国产一卡二卡四卡国 | 蜜臀av夜夜澡人人爽人人桃色 | 免费麻豆| 狠狠干狠狠色 | 狠狠狠色丁香婷婷综合久久五月 | 国产剧情一区二区在线观看 | 亚洲国产午夜精品 | 青青河边草免费直播 | 久久久久久麻豆 | 欧美aaa大片 | 91av在线视频免费观看 | 国产91精品一区二区 | 夜夜躁天天躁很躁波 | 国产97在线视频 | 亚洲成人av免费 | 久久激情网站 | 最近日本韩国中文字幕 | 免费h精品视频在线播放 | 精品一区二区在线免费观看 | 人人超碰免费 | 亚洲乱码久久久 | 国产三级国产精品国产专区50 | 久草视频国产 | 正在播放国产一区 | 久久久视频在线 | 伊人亚洲精品 | 狠狠躁日日躁狂躁夜夜躁 | 国产精品一区二区中文字幕 | 最新av在线免费观看 | 成年人视频在线 | 国产精品毛片一区视频 | 久久精品99视频 | 激情久久久久 | 女人18毛片90分钟 | 91爱看片| 色资源二区在线视频 | 日韩一区二区久久 | 国产一区二区在线免费观看 | 99视频在线观看免费 | av动图| 国产视频中文字幕 | 日韩高清精品免费观看 | 国产精品av电影 | 亚洲久草网 | 日韩资源在线播放 | 欧美a级成人淫片免费看 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 欧美一级欧美一级 | 操操日日 | 日韩一区在线播放 | 亚洲精品国产综合99久久夜夜嗨 | 大型av综合网站 | 91在线一区 | 日韩久久久久久久久久 | 国产在线a不卡 | 中日韩欧美精彩视频 | 狠狠色丁香久久婷婷综合五月 | 狠狠艹夜夜干 | 日本精品午夜 | 13日本xxxxxⅹxxx20| 日韩中文字幕视频在线观看 | 日韩一级理论片 | 999电影免费在线观看 | 国产伦精品一区二区三区高清 | 99精品国产在热久久 | 国产一级小视频 | 四虎永久精品在线 | 国产网站在线免费观看 | 国产资源免费 | 天天操天天操天天操天天操天天操 | 成人高清在线 | 能在线观看的日韩av | 亚洲精品国精品久久99热一 | 久久不卡日韩美女 | 青青视频一区 | 中文字幕五区 | 久久免费成人精品视频 | 国产尤物在线 | 久久久亚洲麻豆日韩精品一区三区 | 国产人成在线视频 | 久久精品xxx | 亚洲国产手机在线 | 欧美日韩中文字幕在线视频 | 亚洲午夜激情网 | 午夜久久久久久久久 | av线上免费看 | 麻豆视频在线免费观看 | 日本精品一区二区在线观看 | 美女国产网站 | 99热在线国产 | 久久精品人 | 天天插天天干天天操 | 亚州av网站 | 国内精品久久久久国产 | 久草电影在线 | 亚洲精品字幕在线观看 | av免费电影在线观看 | 2019中文字幕第一页 | 日韩欧美91 | 成年在线观看 | 激情六月婷婷久久 | 国产精品久99 | 国产成人精品一二三区 | 综合色爱| 久久综合中文字幕 | 在线观看av网站 | 日韩最新中文字幕 | 国产精品国产三级国产aⅴ无密码 | 欧美国产日韩激情 | 黄色av电影免费观看 | 国产中文字幕网 | 国产网站av | 国产91探花 | 2021av在线| av高清不卡 | 99热高清 | 天天操夜夜操国产精品 | 欧美日韩一二三四区 | 亚洲人天堂 | 91丨九色丨高潮 | 99久久精品免费看国产 | 精品资源在线 | 97在线观看免费观看 | 一级α片 | 最近中文字幕久久 | 成人av在线直播 | 国产精品99免视看9 国产精品毛片一区视频 | 国产一区二区在线影院 | 一区精品久久 | 亚洲日本欧美 | 天天操天天干天天干 | 免费观看特级毛片 | www.97色.com | 国产成人av电影 | 中文字幕在线一区二区三区 | www.天天干.com | 欧美一级在线 | 在线视频18在线视频4k | 97视频入口免费观看 | 欧洲成人av | 96精品高清视频在线观看软件特色 | 日日干夜夜操视频 | 毛片网站免费在线观看 | 一区二区视频电影在线观看 | 91精品看片 | 综合网婷婷 | 日韩国产精品久久久久久亚洲 | 99久久久国产精品 | 夜夜躁日日躁狠狠躁 | 国产亚洲综合性久久久影院 | 国产二区精品 | 肉色欧美久久久久久久免费看 | 香蕉在线观看 | 国产精品一区二区62 | 在线观看日韩精品 | 日日爽天天操 | 人人干网 | 欧洲在线免费视频 | 四虎成人精品 | 国产91粉嫩白浆在线观看 | 激情婷婷六月 | 国产精品完整版 | 免费一级片观看 | 国产丝袜高跟 | 五月婷婷六月综合 | 操操操影院 | 成年人在线看视频 | 精品色综合 | 午夜精品区 | 欧美一区视频 | 久久视频在线观看中文字幕 | 91精品国产92久久久久 | 久久狠狠婷婷 | 国产亚洲一级高清 | 99久久久久久久久久 | 91亚州| 99久久精品免费看国产四区 | 欧美精品久久久久久久久久白贞 | 国产日韩在线视频 | 久久99精品久久久久久久久久久久 | 九九九九精品九九九九 | 亚洲片在线 | 久久亚洲婷婷 | 欧美激情视频在线免费观看 | 在线视频99 | 成人黄色大片网站 | 91在线国内视频 | 九九色视频 | 国产精品美女久久久久久久 | 欧美精品一区二区三区四区在线 | 色婷婷视频在线观看 | 毛片网站免费在线观看 | 国产精品久久久久久久久久尿 | 午夜一级免费电影 | 久久免费成人精品视频 | 青青看片 | 日韩天天操 | 91精品播放| 毛片网在线播放 | 麻豆国产网站 | 久久久久久免费网 | 91激情视频在线 | 国产亚洲成人网 | 99久免费精品视频在线观看 | av中文字幕av| 亚洲第一成网站 | 国产午夜在线观看 | 国产热re99久久6国产精品 | 久久精品一二三区 | 色婷在线 | 九九在线免费视频 | 日韩在线观看第一页 | avlulu久久精品 | 在线 欧美 日韩 | 色综合天天天天做夜夜夜夜做 | 精品国产一区二区三区在线 | 456成人精品影院 | 国产精品12 | 99久久精品国产一区二区成人 | www.精选视频.com | 精选久久 | 国产精品免费观看在线 | 在线观看第一页 | 久草视频在线免费看 | 日韩视频免费在线 | 国产精品18久久久久久久网站 | 中文字幕一区二区三区久久蜜桃 | 久久精品男人的天堂 | 久久综合综合久久综合 | 九九九热视频 | 91综合色 | 久爱精品在线 | 亚洲国产中文字幕 | 午夜精品一区二区三区在线播放 | www日 | 午夜精品福利在线 | 日韩成人在线一区二区 | 特级黄色视频毛片 | 免费视频色 | 欧美韩日视频 | 在线看国产日韩 | 国产一级视频在线免费观看 | 日本视频久久久 | 免费看黄网站在线 | 久久成人精品电影 | 亚洲涩涩一区 | 国产三级香港三韩国三级 | 韩日色视频 | 97综合在线 | 91成人天堂久久成人 | 999久久a精品合区久久久 | 97网在线观看| 超级碰视频 | 成人免费观看视频网站 | 99精品国产免费久久久久久下载 | 国产精品一区二区 91 | 国产精品乱码高清在线看 | 一区二区三区在线免费观看视频 | 91精品国产自产在线观看永久 | 在线欧美最极品的av | 日本公妇在线观看 | 色吊丝在线永久观看最新版本 | 国产成人免费av电影 | 精品国内自产拍在线观看视频 | 亚洲伊人第一页 | 在线观看黄色国产 | 亚洲女在线 | 91黄色免费看 | 24小时日本在线www免费的 | 夜添久久精品亚洲国产精品 | 在线亚洲免费视频 | 99爱国产精品| 亚洲精品久久久久中文字幕m男 | 国产精品一二 | 国产男女爽爽爽免费视频 | 亚洲视频大全 | 国产成人亚洲精品自产在线 | 一区在线观看 | 麻豆一区二区 | 久久婷婷精品 | 69人人| 91亚洲精品久久久 | 欧美亚洲成人免费 | 黄色小说免费观看 | 国产精品美女久久 | 天天狠狠操 | 国产午夜精品一区二区三区嫩草 | 久久九九免费 | 欧美三级高清 | 婷婷在线观看视频 | 久久九九影院 | 欧美动漫一区二区三区 | 夜夜操综合网 | 夜夜高潮夜夜爽国产伦精品 | 香蕉影视app | 成人久久18免费网站 | 国产在线视频资源 | 激情久久一区二区三区 | 亚洲午夜久久久影院 | 免费看的国产视频网站 | 91精品久久久久久久91蜜桃 | free,性欧美| 51精品国自产在线 | 成人九九视频 | 99热这里精品 | 久久久久久福利 | 国产一级高清 | 日韩一级黄色大片 | 91av在线免费视频 | 国产美女免费观看 | 亚洲国产黄色 | 亚洲天堂网站 | av在线a| 日产乱码一二三区别在线 | 99色在线观看视频 | av最新资源| 81国产精品久久久久久久久久 | 天天艹天天 | 成人福利在线观看 | 亚洲国产丝袜在线观看 | 亚洲一二三区精品 | 久久免费精品视频 | 久久伦理影院 | 日韩亚洲欧美中文字幕 | aaaaaa毛片 | 日本久久综合网 | 91麻豆精品国产91久久久久久久久 | 国产精品 日韩精品 | 91丨九色丨国产丨porny精品 | 国产一级大片免费看 | 日本成人中文字幕在线观看 | 久草视频视频在线播放 | 粉嫩av一区二区三区入口 | 99精品毛片| 久久综合狠狠综合 | 国产婷婷vvvv激情久 | 亚洲精品国内 | 欧美日韩中文字幕综合视频 | 五月婷婷在线观看 | 欧美精品免费在线观看 | 日韩欧美视频一区 | 日韩av偷拍| 午夜狠狠操 | 伊人国产在线播放 | 最近更新中文字幕 | 欧美激情综合五月色丁香 | av女优中文字幕在线观看 | 999毛片| 国产 日韩 在线 亚洲 字幕 中文 | 视频在线在亚洲 | 免费韩国av| 国产在线91精品 | 九草在线观看 | 日韩电影在线视频 | 久热香蕉视频 | 午夜久久精品 | 日韩中文在线字幕 | 久久免费视频网 | 香蕉97视频观看在线观看 | 国产综合在线观看视频 | 精品久久久久久久久久久院品网 | 欧美99热 | 久久久久久久国产精品 | 中文字幕在线看人 | 日韩深夜在线观看 | 亚洲欧美日韩一二三区 | 亚洲视频在线免费观看 | 曰本三级在线 | 91av欧美 | 国产一级视频在线观看 | 久久久电影 | 综合久久一本 | 久久精品免费看 | 色综合天天爱 | 91免费网址 | 久久人人爽人人片av | 国产精品乱码久久 | 国产成人三级在线观看 | 激情视频免费在线 | 最新av在线网站 | 91av在线免费观看 | 日韩在线网址 | 免费三及片 | 三级黄色网络 | 最新中文字幕在线资源 | 国产午夜av | 日p视频 | 久久与婷婷| 国产精品区二区三区日本 | 成人看片| 中文字幕 二区 | 午夜av一区二区三区 | 奇米影视四色8888 | 国产精品久久久久久69 | 国产手机视频在线观看 | 人人澡av| 最新av网址在线 | 婷婷久久一区二区三区 | av免费在线观看网站 | 国产黄视频在线观看 | 精品视频123区在线观看 | 欧美日韩中文在线视频 | 色福利网| 中文字幕免费观看全部电影 | 在线一二区 | 天天射综合 | 天天综合日日夜夜 | 五月婷婷欧美视频 | 久草视频在线免费 | 亚洲黄色在线观看 | 亚洲一级片在线看 | 国产中文字幕在线视频 | 久爱精品在线 | 天堂在线一区二区三区 | 国产91成人 | 日韩在线电影一区 | 天天插伊人 | 国产精品综合久久久久久 | 天天综合天天综合 | 91黄色成人| 九九视频在线播放 | 永久免费精品视频网站 | 成人毛片a | 在线观看日韩国产 | 日本黄色免费在线观看 | 九九免费精品 | 欧美韩国日本在线观看 | 日韩中文字幕免费在线观看 | 国产在线探花 | 久久99爱视频 | 免费视频成人 | 国产精品中文久久久久久久 | 91少妇精拍在线播放 | 日韩免费视频一区二区 | 91精品婷婷国产综合久久蝌蚪 | 蜜桃视频在线视频 | 国产人成免费视频 | 免费特级黄色片 | 涩涩色亚洲一区 | 人人揉人人揉人人揉人人揉97 | 日韩在线免费观看视频 | 天天操天天干天天操天天干 | 亚洲精品免费观看 | 韩日三级在线 | 狂野欧美激情性xxxx | 丁香色婷婷| 国产福利一区二区三区在线观看 | 日韩中文字幕国产精品 | 国产精品亚洲片在线播放 | 狠狠狠色丁香婷婷综合久久五月 | 狠狠色婷婷丁香六月 | 国产一区精品在线观看 | 日b视频在线观看网址 | 丁香婷婷深情五月亚洲 | 黄色aaa级片| 欧美国产日韩久久 | 一性一交视频 | 日韩草比 | 亚洲精品久 | 国产69精品久久久久久久久久 | 久久久久婷 | 超碰在线免费福利 | 婷婷免费视频 | 在线亚州 | 亚洲小视频在线观看 | 狠狠躁夜夜躁人人爽超碰91 | 一级成人网| 久久高视频| 91最新国产 | 五月婷婷激情 | 免费婷婷| 天天天插 | 香蕉久久久久久久 | 日韩二区三区在线观看 | www.黄色小说.com | 91精品伦理 | 久久在线一区 | 欧美成人黄色片 | 五月婷社区 | 黄在线免费看 | 黄色影院在线免费观看 | 高清一区二区 | 国产色婷婷在线 | 一区二区三区不卡在线 | 国产日韩欧美精品在线观看 | 成人国产一区二区 | 一区二区三区日韩视频在线观看 | 国产一级久久 | 国产人成一区二区三区影院 | 九九九九九九精品任你躁 | 国产精品成人在线 | 99中文字幕在线观看 | 精品国产乱码久久 | 亚洲国产大片 | 网站免费黄色 | www.99久久.com| 蜜臀av性久久久久蜜臀aⅴ涩爱 | 青青草国产精品视频 | 免费色av | 日韩午夜精品 | 色视频网站在线观看一=区 a视频免费在线观看 | 久久精品高清 | 亚洲精品人人 | 久久精品视频在线观看免费 | 91在线视频免费 | 亚洲天堂精品视频在线观看 | av超碰在线 | 超碰人人国产 | 在线免费视频 你懂得 | 日韩激情久久 | 欧美 高跟鞋交 xxxxhd | 中文字幕精品三区 | 久久视频国产 | 日韩在线观看一区二区 | 免费看片黄色 | 欧美一级大片在线观看 | 在线播放亚洲激情 | 成人性生活大片 | 在线观看黄网 | 久久久综合香蕉尹人综合网 | 欧美巨大 | 精品字幕在线 | 日韩欧美视频一区二区 | 国产精品99久久久久久小说 | 超碰人人射| 国模一二三区 | 免费瑟瑟网站 | 中文字幕在线国产 | 久久久久久国产精品美女 | 色视频成人在线观看免 | 一区二区三区久久精品 | 国产美女精品视频免费观看 | 国产黄色片久久久 | 婷婷六月在线 | 天操夜夜操| 亚洲色图 校园春色 | 久久久久9999亚洲精品 | 91九色网站 | 三日本三级少妇三级99 | 色婷婷成人网 | 国产精品九九久久久久久久 | 五月在线视频 | 一二三精品视频 | 中文字幕视频在线播放 | 99精品国产99久久久久久97 | 国产精品成人久久久久久久 | 中文字幕大全 | 在线视频中文字幕一区 | 91视频久久久久久 | av电影中文字幕在线观看 | 国产精品福利无圣光在线一区 | 久久精品国产一区 | 在线精品视频免费播放 | 精品亚洲一区二区三区 | 激情综合狠狠 | 操久久网| 久久电影中文字幕视频 | 欧美午夜久久久 | 欧美一级免费在线 | 成年人电影免费在线观看 | 久久久久久久综合色一本 | 精品视频成人 | 少妇做爰k8经典 | 精品视频在线观看 | 国产午夜一区二区 | 91色吧 | 深夜免费福利网站 | 欧美日韩免费观看一区二区三区 | 亚洲精品视频 | 激情五月在线视频 | 日产乱码一二三区别免费 | 国产精品一级视频 | 在线观看视频免费播放 | 99久久婷婷国产综合亚洲 | 久久综合狠狠综合久久综合88 | 国产精品99久久久久久久久 | 狠狠干夜夜 | 国产福利91精品一区二区三区 | 九九久久婷婷 | 在线天堂中文www视软件 | 日日射av| 成人av在线网 | 中文字幕在线视频第一页 | 韩国三级在线一区 | 久久久久亚洲国产精品 | 中文字幕第 | 久久夜色精品国产欧美乱极品 | 伊人夜夜 | 一区免费观看 | 最新高清无码专区 | 一区二区伦理电影 | 在线看成人| 国产成人三级一区二区在线观看一 | 91av综合 | 一区二区激情 | 久久综合免费视频影院 | 久久综合五月天 | 性色av香蕉一区二区 | 激情av网址 | 久久亚洲二区 | 日本一区二区三区免费观看 | 亚洲国产电影在线观看 | 久9在线 | 欧美 日韩 国产 中文字幕 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 最新极品jizzhd欧美 | aaa免费毛片| 久草在线 | 久久精品免费电影 | 国内精品久久久久久久影视简单 | 成人av一区二区兰花在线播放 | 日韩激情久久 | 午夜三级理论 | 六月色婷婷 | 中文字幕日韩av | 美女免费黄视频网站 | 久久综合天天 | 中文字幕日韩精品有码视频 | 日韩久久网站 | 少妇bbr搡bbb搡bbb | 久久草在线免费 | 亚洲精品中文字幕视频 | 丁香伊人网 | 欧美 亚洲 另类 激情 另类 | 一区二区三区电影 | 在线影院中文字幕 | www.狠狠操| 色婷婷影视 | 久久精品综合网 | 久久久.com | 日韩二级毛片 | 国产一区二区三精品久久久无广告 | 亚洲高清视频在线观看免费 | 97在线免费视频观看 | 美女视频久久 | 九九在线视频 | 精品免费久久久久 | 国产视频在线观看免费 | 999视频网 | 国产精品色 | 欧美激情精品久久久久久 | 国产精品成人国产乱一区 | 97日日碰人人模人人澡分享吧 | 在线观看福利网站 | 成年人黄色大全 | 成人av在线看| 日韩精品高清不卡 | 韩国av免费观看 | 国产精品电影一区 | 亚洲视频精选 | 91九色最新 | 久久久国产影视 | 国产精品成人久久 | 91丨九色丨国产在线观看 | 91麻豆精品国产自产 | 五月天激情视频在线观看 | 91精品伦理| 色婷婷六月天 | 国产亚洲精品久久久久久电影 | 天天拍天天爽 | 手机色在线 | 91亚州 | 日韩免费网址 | 久久亚洲免费视频 | 久久免费国产电影 | 国产在线观看免费av | 国产精品成人在线 | 天天色天天上天天操 | 2019免费中文字幕 | 97精品国自产拍在线观看 | 日韩一二区在线 | 欧美日韩在线播放一区 | 午夜黄色| 四虎国产精品永久在线国在线 | 日本大片免费观看在线 | 国产原创中文在线 | 免费久久99精品国产 | 狠狠色伊人亚洲综合网站野外 | 久久综合久久88 | 中文国产字幕在线观看 | 久久免费视频一区 | 日日操天天爽 | 天天插天天射 | 色鬼综合网 | 久久久五月天 | 福利视频 | 九草视频在线观看 | 国产日本在线播放 | 麻豆视频在线看 | 爱av在线网| 成人在线视频论坛 | 亚洲视频中文 | 日韩高清激情 | 久久综合免费视频影院 | 亚洲三级在线免费观看 | av免费黄色 | 天天综合入口 | 欧美国产日韩激情 | 久久成人18免费网站 | 国产午夜精品av一区二区 | 9i看片成人免费看片 | 国产精品一区二区三区在线免费观看 | 精品久久久99 | 深夜免费福利在线 | 中文字幕二区在线观看 | 色视频网址 | 在线三级播放 | 中文字幕在线观看网 | 亚洲在线不卡 | 久久新视频 | 亚洲国产精品99久久久久久久久 | 精品中文字幕在线 | 丁香六月国产 | 国产一级片网站 | av高清免费| 黄色网址国产 | 天天射狠狠干 | 国产精品久久久久久久久费观看 | 国产精品 999 | 在线观看aa | 激情欧美国产 | 偷拍福利视频一区二区三区 | 国产精品成人免费一区久久羞羞 | 亚洲一级片免费观看 | 日产av在线播放 | 99久久精品电影 | 久久99久久99免费视频 | 天天色综合久久 | 色操插| 中文不卡视频 | 日本性xxxxx 亚洲精品午夜久久久 | 最近中文字幕国语免费高清6 | 狠狠狠色丁香综合久久天下网 | 免费精品视频在线观看 | 国产精品资源在线 | 日韩免费一二三区 | 久日精品| 国产 日韩 在线 亚洲 字幕 中文 | 黄色小说免费观看 | 精品国产欧美一区二区三区不卡 | av在线播放国产 | 久久久国际精品 | 99精品免费在线 | 欧美日韩高清一区 | 又湿又紧又大又爽a视频国产 | 日韩三级不卡 | 国产精品中文 | www天天干 | 青青河边草免费直播 | 黄色三级网站在线观看 | 日本公乱妇视频 | 伊人狠狠色 | 91一区一区三区 | 久久国产免费 |