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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Tomcat源码分析 (九)----- HTTP请求处理过程(二)

發(fā)布時(shí)間:2023/10/11 2033 老码农
生活随笔 收集整理的這篇文章主要介紹了 Tomcat源码分析 (九)----- HTTP请求处理过程(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們接著上一篇文章的容器處理來(lái)講,當(dāng)postParseRequest方法返回true時(shí),則由容器繼續(xù)處理,在service方法中有connector.getService().getContainer().getPipeline().getFirst().invoke(request, response)這一行:

  • Connector調(diào)用getService()返回StandardService;
  • StandardService調(diào)用getContainer返回StandardEngine;
  • StandardEngine調(diào)用getPipeline返回與其關(guān)聯(lián)的StandardPipeline;

Engine處理請(qǐng)求

我們?cè)谇懊娴奈恼轮兄v過(guò)StandardEngine的構(gòu)造函數(shù)為自己的Pipeline添加了基本閥StandardEngineValve,代碼如下:

public StandardEngine() {
super();
pipeline.setBasic(new StandardEngineValve());
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch(Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
}

接下來(lái)我們看看StandardEngineValveinvoke()方法。該方法主要是選擇合適的Host,然后調(diào)用Host中pipeline的第一個(gè)Valve的invoke()方法。

public final void invoke(Request request, Response response)
throws IOException, ServletException { // Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
} // Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
該方法很簡(jiǎn)單,校驗(yàn)該Engline 容器是否含有Host容器,如果不存在,返回400錯(cuò)誤,否則繼續(xù)執(zhí)行 host.getPipeline().getFirst().invoke(request, response),可以看到 Host 容器先獲取自己的管道,再獲取第一個(gè)閥門(mén),我們?cè)倏纯丛撻y門(mén)的 invoke 方法。

Host處理請(qǐng)求

分析Host的時(shí)候,我們從Host的構(gòu)造函數(shù)入手,該方法主要是設(shè)置基礎(chǔ)閥門(mén)。

public StandardHost() {
super();
pipeline.setBasic(new StandardHostValve());
}

StandardPipeline調(diào)用getFirst得到第一個(gè)閥去處理請(qǐng)求,由于基本閥是最后一個(gè),所以最后會(huì)由基本閥去處理請(qǐng)求。

StandardHost的Pipeline里面一定有 ErrorReportValve 與 StandardHostValve兩個(gè)Valve,ErrorReportValve主要是檢測(cè) Http 請(qǐng)求過(guò)程中是否出現(xiàn)過(guò)什么異常, 有異常的話, 直接拼裝 html 頁(yè)面, 輸出到客戶端。

我們看看ErrorReportValve的invoke方法:

public void invoke(Request request, Response response)
throws IOException, ServletException {
// Perform the request
// 1. 先將 請(qǐng)求轉(zhuǎn)發(fā)給下一個(gè) Valve
getNext().invoke(request, response);
// 2. 這里的 isCommitted 表明, 請(qǐng)求是正常處理結(jié)束
if (response.isCommitted()) {
return;
}
// 3. 判斷請(qǐng)求過(guò)程中是否有異常發(fā)生
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
if (request.isAsyncStarted() && ((response.getStatus() < 400 &&
throwable == null) || request.isAsyncDispatching())) {
return;
}
if (throwable != null) {
// The response is an error
response.setError();
// Reset the response (if possible)
try {
// 4. 重置 response 里面的數(shù)據(jù)(此時(shí) Response 里面可能有些數(shù)據(jù))
response.reset();
} catch (IllegalStateException e) {
// Ignore
}
// 5. 這就是我們??吹降?500 錯(cuò)誤碼
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
response.setSuspended(false);
try {
// 6. 這里就是將 異常的堆棧信息組合成 html 頁(yè)面, 輸出到前臺(tái)
report(request, response, throwable);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
if (request.isAsyncStarted()) {
// 7. 若是異步請(qǐng)求的話, 設(shè)置對(duì)應(yīng)的 complete (對(duì)應(yīng)的是 異步 Servlet)
request.getAsyncContext().complete();
}
}

該方法首先執(zhí)行了下個(gè)閥門(mén)的 invoke 方法。然后根據(jù)返回的Request 屬性設(shè)置一些錯(cuò)誤信息。那么下個(gè)閥門(mén)是誰(shuí)呢?其實(shí)就是基礎(chǔ)閥門(mén)了:StandardHostValve,該閥門(mén)的 invoke 的方法是如何實(shí)現(xiàn)的呢?

@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException { // Select the Context to be used for this Request
Context context = request.getContext();
if (context == null) {
response.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
sm.getString("standardHost.noContext"));
return;
} // Bind the context CL to the current thread
if( context.getLoader() != null ) {
// Not started - it should check for availability first
// This should eventually move to Engine, it's generic.
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
context.getLoader().getClassLoader());
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
}
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(context.getPipeline().isAsyncSupported());
} // Don't fire listeners during async processing
// If a request init listener throws an exception, the request is
// aborted
boolean asyncAtStart = request.isAsync();
// An async error page may dispatch to another resource. This flag helps
// ensure an infinite error handling loop is not entered
boolean errorAtStart = response.isError();
if (asyncAtStart || context.fireRequestInitEvent(request)) { // Ask this Context to process this request
try {
context.getPipeline().getFirst().invoke(request, response);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (errorAtStart) {
container.getLogger().error("Exception Processing " +
request.getRequestURI(), t);
} else {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
} // If the request was async at the start and an error occurred then
// the async error handling will kick-in and that will fire the
// request destroyed event *after* the error handling has taken
// place
if (!(request.isAsync() || (asyncAtStart &&
request.getAttribute(
RequestDispatcher.ERROR_EXCEPTION) != null))) {
// Protect against NPEs if context was destroyed during a
// long running request.
if (context.getState().isAvailable()) {
if (!errorAtStart) {
// Error page processing
response.setSuspended(false); Throwable t = (Throwable) request.getAttribute(
RequestDispatcher.ERROR_EXCEPTION); if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
} context.fireRequestDestroyEvent(request);
}
}
} // Access a session (if present) to update last accessed time, based on a
// strict interpretation of the specification
if (ACCESS_SESSION) {
request.getSession(false);
} // Restore the context classloader
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
StandardHostValve.class.getClassLoader());
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader
(StandardHostValve.class.getClassLoader());
}
}
首先校驗(yàn)了Request 是否存在 Context,其實(shí)在執(zhí)行 CoyoteAdapter.postParseRequest 方法的時(shí)候就設(shè)置了,如果Context 不存在,就返回500,接著還是老套路:context.getPipeline().getFirst().invoke,該管道獲取的是基礎(chǔ)閥門(mén):StandardContextValve,我們還是關(guān)注他的 invoke 方法。

Context處理請(qǐng)求

接著Context會(huì)去處理請(qǐng)求,同理,StandardContextValve的invoke方法會(huì)被調(diào)用:

@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Disallow any direct access to resources under WEB-INF or META-INF
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} // Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} // Acknowledge the request
try {
response.sendAcknowledgement();
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
} if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}

Wrapper處理請(qǐng)求

Wrapper是一個(gè)Servlet的包裝,我們先來(lái)看看構(gòu)造方法。主要作用就是設(shè)置基礎(chǔ)閥門(mén)StandardWrapperValve。

public StandardWrapper() {
super();
swValve=new StandardWrapperValve();
pipeline.setBasic(swValve);
broadcaster = new NotificationBroadcasterSupport();
}

接下來(lái)我們看看StandardWrapperValveinvoke()方法。

@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException { // Initialize local variables we may need
boolean unavailable = false;
Throwable throwable = null;
// This should be a Request attribute...
long t1=System.currentTimeMillis();
requestCount.incrementAndGet();
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent(); // Check for the application being marked unavailable
if (!context.getState().isAvailable()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardContext.isUnavailable"));
unavailable = true;
} // Check for the servlet being marked unavailable
if (!unavailable && wrapper.isUnavailable()) {
container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
unavailable = true;
} // Allocate a servlet instance to process this request
try {
// 關(guān)鍵點(diǎn)1:這兒調(diào)用Wrapper的allocate()方法分配一個(gè)Servlet實(shí)例
if (!unavailable) {
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
} catch (ServletException e) {
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), StandardWrapper.getRootCause(e));
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
} MessageBytes requestPathMB = request.getRequestPathMB();
DispatcherType dispatcherType = DispatcherType.REQUEST;
if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
requestPathMB);
// Create the filter chain for this request
// 關(guān)鍵點(diǎn)2,創(chuàng)建過(guò)濾器鏈,類(lèi)似于Pipeline的功能
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); // Call the filter chain for this request
// NOTE: This also calls the servlet's service() method
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
// 關(guān)鍵點(diǎn)3,調(diào)用過(guò)濾器鏈的doFilter,最終會(huì)調(diào)用到Servlet的service方法
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
// 關(guān)鍵點(diǎn)3,調(diào)用過(guò)濾器鏈的doFilter,最終會(huì)調(diào)用到Servlet的service方法
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
} }
} catch (ClientAbortException e) {
throwable = e;
exception(request, response, e);
} catch (IOException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
// throwable = e;
// exception(request, response, e);
wrapper.unavailable(e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
// Do not save exception in 'throwable', because we
// do not want to do exception(request, response, e) processing
} catch (ServletException e) {
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceExceptionRoot",
wrapper.getName(), context.getName(), e.getMessage()),
rootCause);
}
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} // Release the filter chain (if any) for this request
// 關(guān)鍵點(diǎn)4,釋放掉過(guò)濾器鏈及其相關(guān)資源
if (filterChain != null) {
filterChain.release();
} // 關(guān)鍵點(diǎn)5,釋放掉Servlet及相關(guān)資源
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
} // If this servlet has been marked permanently unavailable,
// unload it and release this instance
// 關(guān)鍵點(diǎn)6,如果servlet被標(biāo)記為永遠(yuǎn)不可達(dá),則需要卸載掉它,并釋放這個(gè)servlet實(shí)例
try {
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.unloadException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
long t2=System.currentTimeMillis(); long time=t2-t1;
processingTime += time;
if( time > maxTime) maxTime=time;
if( time < minTime) minTime=time;
}

通過(guò)閱讀源碼,我們發(fā)現(xiàn)了幾個(gè)關(guān)鍵點(diǎn)?,F(xiàn)羅列如下,后面我們會(huì)逐一分析這些關(guān)鍵點(diǎn)相關(guān)的源碼。

  1. 關(guān)鍵點(diǎn)1:這兒調(diào)用Wrapper的allocate()方法分配一個(gè)Servlet實(shí)例
  2. 關(guān)鍵點(diǎn)2,創(chuàng)建過(guò)濾器鏈,類(lèi)似于Pipeline的功能
  3. 關(guān)鍵點(diǎn)3,調(diào)用過(guò)濾器鏈的doFilter,最終會(huì)調(diào)用到Servlet的service方法
  4. 關(guān)鍵點(diǎn)4,釋放掉過(guò)濾器鏈及其相關(guān)資源
  5. 關(guān)鍵點(diǎn)5,釋放掉Servlet及相關(guān)資源
  6. 關(guān)鍵點(diǎn)6,如果servlet被標(biāo)記為永遠(yuǎn)不可達(dá),則需要卸載掉它,并釋放這個(gè)servlet實(shí)例

關(guān)鍵點(diǎn)1 - Wrapper分配Servlet實(shí)例

我們來(lái)分析一下Wrapper.allocate()方法

@Override
public Servlet allocate() throws ServletException { // If we are currently unloading this servlet, throw an exception
// 卸載過(guò)程中,不能分配Servlet
if (unloading) {
throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
} boolean newInstance = false; // If not SingleThreadedModel, return the same instance every time
// 如果Wrapper沒(méi)有實(shí)現(xiàn)SingleThreadedModel,則每次都會(huì)返回同一個(gè)Servlet
if (!singleThreadModel) {
// Load and initialize our instance if necessary
// 實(shí)例為null或者實(shí)例還未初始化,使用synchronized來(lái)保證并發(fā)時(shí)的原子性
if (instance == null || !instanceInitialized) {
synchronized (this) {
if (instance == null) {
try {
if (log.isDebugEnabled()) {
log.debug("Allocating non-STM instance");
} // Note: We don't know if the Servlet implements
// SingleThreadModel until we have loaded it.
// 加載Servlet
instance = loadServlet();
newInstance = true;
if (!singleThreadModel) {
// For non-STM, increment here to prevent a race
// condition with unload. Bug 43683, test case
// #3
countAllocated.incrementAndGet();
}
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
}
// 初始化Servlet
if (!instanceInitialized) {
initServlet(instance);
}
}
} if (singleThreadModel) {
if (newInstance) {
// Have to do this outside of the sync above to prevent a
// possible deadlock
synchronized (instancePool) {
instancePool.push(instance);
nInstances++;
}
}
}
// 非單線程模型,直接返回已經(jīng)創(chuàng)建的Servlet,也就是說(shuō),這種情況下只會(huì)創(chuàng)建一個(gè)Servlet
else {
if (log.isTraceEnabled()) {
log.trace(" Returning non-STM instance");
}
// For new instances, count will have been incremented at the
// time of creation
if (!newInstance) {
countAllocated.incrementAndGet();
}
return instance;
}
} // 如果是單線程模式,則使用servlet對(duì)象池技術(shù)來(lái)加載多個(gè)Servlet
synchronized (instancePool) {
while (countAllocated.get() >= nInstances) {
// Allocate a new instance if possible, or else wait
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
if (log.isTraceEnabled()) {
log.trace(" Returning allocated STM instance");
}
countAllocated.incrementAndGet();
return instancePool.pop();
}
}

總結(jié)下來(lái),注意以下幾點(diǎn)即可:

  1. 卸載過(guò)程中,不能分配Servlet
  2. 如果不是單線程模式,則每次都會(huì)返回同一個(gè)Servlet(默認(rèn)Servlet實(shí)現(xiàn)方式)
  3. Servlet實(shí)例為null或者Servlet實(shí)例還未初始化,使用synchronized來(lái)保證并發(fā)時(shí)的原子性
  4. 如果是單線程模式,則使用servlet對(duì)象池技術(shù)來(lái)加載多個(gè)Servlet

接下來(lái)我們看看loadServlet()方法

public synchronized Servlet loadServlet() throws ServletException {

    // Nothing to do if we already have an instance or an instance pool
if (!singleThreadModel && (instance != null))
return instance; PrintStream out = System.out;
if (swallowOutput) {
SystemLogHandler.startCapture();
} Servlet servlet;
try {
long t1=System.currentTimeMillis();
// Complain if no servlet class has been specified
if (servletClass == null) {
unavailable(null);
throw new ServletException
(sm.getString("standardWrapper.notClass", getName()));
} // 關(guān)鍵的地方,就是通過(guò)實(shí)例管理器,創(chuàng)建Servlet實(shí)例,而實(shí)例管理器是通過(guò)特殊的類(lèi)加載器來(lái)加載給定的類(lèi)
InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
try {
servlet = (Servlet) instanceManager.newInstance(servletClass);
} catch (ClassCastException e) {
unavailable(null);
// Restore the context ClassLoader
throw new ServletException
(sm.getString("standardWrapper.notServlet", servletClass), e);
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
unavailable(null); // Added extra log statement for Bugzilla 36630:
// https://bz.apache.org/bugzilla/show_bug.cgi?id=36630
if(log.isDebugEnabled()) {
log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
} // Restore the context ClassLoader
throw new ServletException
(sm.getString("standardWrapper.instantiate", servletClass), e);
} if (multipartConfigElement == null) {
MultipartConfig annotation =
servlet.getClass().getAnnotation(MultipartConfig.class);
if (annotation != null) {
multipartConfigElement =
new MultipartConfigElement(annotation);
}
} // Special handling for ContainerServlet instances
// Note: The InstanceManager checks if the application is permitted
// to load ContainerServlets
if (servlet instanceof ContainerServlet) {
((ContainerServlet) servlet).setWrapper(this);
} classLoadTime=(int) (System.currentTimeMillis() -t1); if (servlet instanceof SingleThreadModel) {
if (instancePool == null) {
instancePool = new Stack<>();
}
singleThreadModel = true;
} // 調(diào)用Servlet的init方法
initServlet(servlet); fireContainerEvent("load", this); loadTime=System.currentTimeMillis() -t1;
} finally {
if (swallowOutput) {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
if (getServletContext() != null) {
getServletContext().log(log);
} else {
out.println(log);
}
}
}
}
return servlet;
}

關(guān)鍵的地方有兩個(gè):

  1. 通過(guò)實(shí)例管理器,創(chuàng)建Servlet實(shí)例,而實(shí)例管理器是通過(guò)特殊的類(lèi)加載器來(lái)加載給定的類(lèi)
  2. 調(diào)用Servlet的init方法

關(guān)鍵點(diǎn)2 - 創(chuàng)建過(guò)濾器鏈

創(chuàng)建過(guò)濾器鏈?zhǔn)钦{(diào)用的org.apache.catalina.core.ApplicationFilterFactorycreateFilterChain()方法。我們來(lái)分析一下這個(gè)方法。該方法需要注意的地方已經(jīng)在代碼的comments里面說(shuō)明了。

public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) { // If there is no servlet to execute, return null
if (servlet == null)
return null; // Create and initialize a filter chain object
// 1. 如果加密打開(kāi)了,則可能會(huì)多次調(diào)用這個(gè)方法
// 2. 為了避免重復(fù)生成filterChain對(duì)象,所以會(huì)將filterChain對(duì)象放在Request里面進(jìn)行緩存
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request) request;
if (Globals.IS_SECURITY_ENABLED) {
// Security: Do not recycle
filterChain = new ApplicationFilterChain();
} else {
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
} else {
// Request dispatcher in use
filterChain = new ApplicationFilterChain();
} filterChain.setServlet(servlet);
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported()); // Acquire the filter mappings for this Context
StandardContext context = (StandardContext) wrapper.getParent();
// 從這兒看出過(guò)濾器鏈對(duì)象里面的元素是根據(jù)Context里面的filterMaps來(lái)生成的
FilterMap filterMaps[] = context.findFilterMaps(); // If there are no filter mappings, we are done
if ((filterMaps == null) || (filterMaps.length == 0))
return (filterChain); // Acquire the information we will need to match filter mappings
DispatcherType dispatcher =
(DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR); String requestPath = null;
Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
if (attribute != null){
requestPath = attribute.toString();
} String servletName = wrapper.getName(); // Add the relevant path-mapped filters to this filter chain
// 類(lèi)型和路徑都匹配的情況下,將context.filterConfig放到過(guò)濾器鏈里面
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
if (!matchFiltersURL(filterMaps[i], requestPath))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
} // Add filters that match on servlet name second
// 類(lèi)型和servlet名稱(chēng)都匹配的情況下,將context.filterConfig放到過(guò)濾器鏈里面
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
if (!matchFiltersServlet(filterMaps[i], servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
} // Return the completed filter chain
return filterChain;
}

關(guān)鍵點(diǎn)3 - 調(diào)用過(guò)濾器鏈的doFilter

ApplicationFilterChain類(lèi)的doFilter函數(shù)代碼如下,它會(huì)將處理委托給internalDoFilter函數(shù)。

@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException { if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}

ApplicationFilterChain類(lèi)的internalDoFilter函數(shù)代碼如下:

// 1. `internalDoFilter`方法通過(guò)pos和n來(lái)調(diào)用過(guò)濾器鏈里面的每個(gè)過(guò)濾器。pos表示當(dāng)前的過(guò)濾器下標(biāo),n表示總的過(guò)濾器數(shù)量
// 2. `internalDoFilter`方法最終會(huì)調(diào)用servlet.service()方法
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException { // Call the next filter if there is one
// 1. 當(dāng)pos小于n時(shí), 則執(zhí)行Filter
if (pos < n) {
// 2. 得到 過(guò)濾器 Filter,執(zhí)行一次post++
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter(); if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
// 4. 這里的 filter 的執(zhí)行 有點(diǎn)遞歸的感覺(jué), 通過(guò) pos 來(lái)控制從 filterChain 里面拿出那個(gè) filter 來(lái)進(jìn)行操作
// 這里把this(filterChain)傳到自定義filter里面,我們自定義的filter,會(huì)重寫(xiě)doFilter,在這里會(huì)被調(diào)用,doFilter里面會(huì)執(zhí)行業(yè)務(wù)邏輯,如果執(zhí)行業(yè)務(wù)邏輯成功,則會(huì)調(diào)用 filterChain.doFilter(servletRequest, servletResponse); ,filterChain就是這里傳過(guò)去的this;如果業(yè)務(wù)邏輯執(zhí)行失敗,則return,filterChain終止,后面的servlet.service(request, response)也不會(huì)執(zhí)行了
// 所以在 Filter 里面所調(diào)用 return, 則會(huì)終止 Filter 的調(diào)用, 而下面的 Servlet.service 更本就沒(méi)有調(diào)用到
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
} // We fell off the end of the chain -- call the servlet instance
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
} if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
//當(dāng)pos等于n時(shí),過(guò)濾器都執(zhí)行完畢,終于執(zhí)行了熟悉的servlet.service(request, response)方法。
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}

自定義Filter

@WebFilter(urlPatterns = "/*", filterName = "myfilter")
public class FileterController implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter初始化中");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("登錄邏輯");
if("登錄失敗"){
response.getWriter().write("登錄失敗");
//后面的攔截器和servlet都不會(huì)執(zhí)行了
return;
}
//登錄成功,執(zhí)行下一個(gè)過(guò)濾器
filterChain.doFilter(servletRequest, servletResponse);
} @Override
public void destroy() {
System.out.println("Filter銷(xiāo)毀中");
}
}
  • pos和n是ApplicationFilterChain的成員變量,分別表示過(guò)濾器鏈的當(dāng)前位置和過(guò)濾器總數(shù),所以當(dāng)pos小于n時(shí),會(huì)不斷執(zhí)行ApplicationFilterChain的doFilter方法;
  • 當(dāng)pos等于n時(shí),過(guò)濾器都執(zhí)行完畢,終于執(zhí)行了熟悉的servlet.service(request, response)方法。

總結(jié)

以上是生活随笔為你收集整理的Tomcat源码分析 (九)----- HTTP请求处理过程(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

久久精品99国产精品亚洲最刺激 | 日本中文字幕在线免费观看 | 高清免费在线视频 | 国产免费午夜 | 黄网站大全| 园产精品久久久久久久7电影 | 日本中出在线观看 | av在线播放免费 | 2019精品手机国产品在线 | 欧美另类一二三四区 | 国产精品久久久久一区二区三区 | 国产亚洲亚洲 | 91爱爱免费观看 | 中文字幕一区二区三区四区久久 | 天天干天天弄 | 97超碰中文字幕 | 亚洲激情av | 亚洲精品欧美精品 | 91九色老| 久久久久久久久影视 | 波多野结衣电影久久 | 国色天香av| 碰天天操天天 | 中文字幕永久 | 麻豆视频入口 | 久久久五月婷婷 | 亚洲综合色播 | 免费下载高清毛片 | 97超视频免费观看 | 在线免费观看av网站 | 欧美一级电影在线观看 | 久久精品国产久精国产 | 中文资源在线官网 | 亚洲视频在线观看免费 | 久久综合综合久久综合 | 狠狠色狠狠色综合系列 | 国产涩涩在线观看 | www免费黄色 | 色欧美日韩 | 九九热精品视频在线播放 | 久久99精品国产麻豆婷婷 | 国产原创中文在线 | 婷婷深爱五月 | 视频直播国产精品 | 999在线精品| 国产精品嫩草影院99网站 | 欧美日本三级 | 国内久久精品视频 | 99久在线精品99re8热视频 | 久艹视频在线免费观看 | 国产亚洲精品久久久久久大师 | 久久久久高清 | 精品色综合 | 成人av电影在线 | 97干com| 国内外成人免费在线视频 | 国产网红在线观看 | 在线成人高清电影 | 99精品国产免费久久 | 久久久久电影 | 黄a在线看 | 成人av电影免费在线播放 | 久久国产精品99久久久久久丝袜 | 婷婷综合久久 | 国产专区一 | 国产精品视频免费看 | 日韩精品一区二区三区中文字幕 | 狠狠久久| 免费看的国产视频网站 | 中文字幕免费久久 | 欧美亚洲xxx | 国产女v资源在线观看 | 日韩电影黄色 | 2023亚洲精品国偷拍自产在线 | 婷婷综合久久 | 麻豆你懂的 | 在线观看国产麻豆 | 中文字幕人成乱码在线观看 | 日韩精品免费在线观看 | 视频1区2区 | 国产在线观看一 | 香蕉手机在线 | 国产午夜视频在线观看 | 高清一区二区三区 | 国产精品美女视频 | 在线日本v二区不卡 | 国产精品96久久久久久吹潮 | 亚洲精品国产精品国自产在线 | 中文字幕精品一区二区三区电影 | 91九色蝌蚪在线 | 婷婷5月激情5月 | 日韩免费福利 | 中国一级片在线观看 | 亚洲1区 在线 | 一级黄色免费 | 黄色在线小网站 | 亚洲一区二区视频在线播放 | 麻豆91精品91久久久 | 国产成人免费 | 欧美午夜寂寞影院 | 久久精品视频观看 | 免费日韩在线 | 久久久亚洲影院 | 日韩免费一级a毛片在线播放一级 | 在线视频 日韩 | 国产中文字幕在线免费观看 | 日日操天天爽 | 粉嫩av一区二区三区四区在线观看 | 天天操天天色天天射 | 日韩免费大片 | 最新精品视频在线 | 五月婷婷中文 | 香蕉在线影院 | 一区二区三区视频网站 | 久久久麻豆精品一区二区 | 欧美一级片免费 | 天天插天天色 | av在线免费网站 | 国产不卡网站 | 伊人天天干 | 精品国产理论 | 青春草免费视频 | 在线观看免费成人av | 国产精品不卡在线播放 | 一区二区三区免费看 | 欧美性生活免费看 | 天天操天天干天天操天天干 | 四虎成人精品 | 亚洲欧洲国产日韩精品 | 免费进去里的视频 | 欧美性久久久久久 | 在线精品播放 | 国产精品一区二区你懂的 | 91网站免费观看 | 又紧又大又爽精品一区二区 | 精品视频99 | 亚欧日韩av | 麻豆视频成人 | 亚洲成人av在线播放 | 人人爽人人爽人人片 | 国产一区二区高清视频 | 国产专区第一页 | 欧美xxxx性xxxxx高清 | 天天干天天碰 | 91在线免费播放 | 97在线精品国自产拍中文 | 黄色99视频 | 久久永久免费视频 | 成人看片 | 国产午夜亚洲精品 | 很污的网站 | 99热最新网址| 国产精品福利午夜在线观看 | 日韩中文三级 | 国产精品手机在线 | 天天插夜夜操 | 国产精品久久久久久久av电影 | 精品久久久久久一区二区里番 | 久久成人在线视频 | 日本久久成人中文字幕电影 | 日韩网站一区 | 国产不卡在线播放 | 97在线视频观看 | 狠狠色狠狠色终合网 | 精品国产一区二区三区在线 | 精品国产一区二区三区日日嗨 | 全久久久久久久久久久电影 | 一区二区中文字幕在线观看 | 久久久久久久久久亚洲精品 | 亚洲精品国精品久久99热一 | 日本久草电影 | 免费a级大片 | av色影院 | 成人国产精品电影 | 国产婷婷vvvv激情久 | 日日夜夜亚洲 | 一级久久精品 | 一本一本久久a久久精品综合妖精 | 99视频免费看 | 精品久久片 | 99色99| 91av欧美 | 国产高清成人在线 | 在线视频免费观看 | 国产亚洲精品久久久久久无几年桃 | 久久精品国产一区二区三 | 丁香花中文在线免费观看 | 人人澡人人添人人爽一区二区 | 在线观看日韩中文字幕 | 亚洲少妇激情 | www.久久久.com| 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 日韩电影精品一区 | 中文网丁香综合网 | 337p日本大胆噜噜噜噜 | av电影一区| 中文字幕在线播放日韩 | 日韩在线视频观看免费 | 日av免费 | 香蕉精品在线观看 | 伊人看片| 精品99在线| 99精品久久只有精品 | 丁香 婷婷 激情 | 91看片淫黄大片在线播放 | 天天干天天干天天干 | 亚洲国产日韩一区 | 亚洲japanese制服美女 | 香蕉在线视频观看 | 一区二区三区免费看 | 日韩网站视频 | 五月婷婷视频在线 | 欧美精品生活片 | 久久精品一区二区三区视频 | 日本三级吹潮在线 | 国产精品对白一区二区三区 | 亚洲日本在线视频观看 | 日韩欧美在线视频一区二区三区 | 色婷婷av一区| 精品国产伦一区二区三区观看方式 | 在线播放 日韩专区 | 国产专区欧美专区 | 四虎国产永久在线精品 | 亚洲少妇激情 | 国产一线天在线观看 | avhd高清在线谜片 | av色图天堂网 | 亚洲精品久久久久58 | 久久久久免费精品视频 | 超碰人人舔 | 99久久综合国产精品二区 | 国产中文字幕第一页 | 丁香婷婷在线观看 | 国产人成免费视频 | 一级一级一片免费 | 99中文字幕视频 | 精品视频在线免费 | 国产精品手机在线观看 | 成人av动漫在线 | 中文av网站 | 美女视频免费精品 | 99精品国产福利在线观看免费 | 欧美男同网站 | 国产美女视频一区 | 欧美激情视频一二三区 | 国产精品igao视频网网址 | 欧美日韩中文字幕在线视频 | 国产日产高清dvd碟片 | 天天干天天操天天拍 | 天堂av在线网 | 黄色三级在线观看 | 91在线免费观看网站 | 日韩有码第一页 | 伊人永久在线 | 国语对白少妇爽91 | 久久伊人国产精品 | 99精品久久久久久久久久综合 | 亚洲一区 影院 | 依人成人综合网 | 久久久激情视频 | 中文一区二区三区在线观看 | 国产特级毛片aaaaaa高清 | 国产亚洲综合在线 | 亚洲美女视频网 | 久久久久亚洲a | 碰碰影院 | 91麻豆精品| 99精品国产一区二区三区麻豆 | 久久综合色一综合色88 | 日韩区视频 | 最近中文字幕视频网 | 日韩一区二区三区免费视频 | 九色91av| 在线国产精品一区 | 97国产超碰 | 国产伦理一区二区 | 久久久久久蜜桃一区二区 | 九九视频免费 | 亚洲日本成人 | 亚洲天堂网在线观看视频 | 美女黄网久久 | 国产精品久久久久婷婷 | www.狠狠色.com | 97在线视频网站 | 色综合天天天天做夜夜夜夜做 | 免费在线观看av网站 | 国产成人精品午夜在线播放 | 伊人午夜| 五月婷婷亚洲 | 国产在线一区二区 | av线上免费观看 | 在线日本看片免费人成视久网 | 久久综合久色欧美综合狠狠 | 日韩av在线高清 | 国产不卡在线观看 | 久久久色| www免费看片com | 人人干人人做 | 久视频在线 | 97av影院 | 五月婷婷综合激情 | 亚洲爽爽网 | www.狠狠干 | 国产精品久久久久久99 | 中文字幕成人网 | 亚洲精品免费观看 | 国产视频色| 91精品伦理 | 毛片一区二区 | 亚洲日本va在线观看 | 国产亚洲精品久久久久久网站 | av官网在线 | 福利视频区| 人人干97| 91免费网| 成人国产精品久久久春色 | 偷拍视频一区 | 一区二区三区中文字幕在线观看 | 手机看片中文字幕 | 久久精品中文字幕少妇 | www久草| 日韩欧美在线综合网 | 亚洲国产精品视频在线观看 | 在线之家免费在线观看电影 | 九九热只有这里有精品 | h视频在线看 | 在线观看 亚洲 | 成年免费在线视频 | 国产精品白丝jk白祙 | 日本黄区免费视频观看 | 亚洲九九 | 国产精品一区二区三区四 | 99在线高清视频在线播放 | 色九九在线 | 国产精品免费av | 欧美精品在线观看一区 | 男女拍拍免费视频 | 在线你懂的视频 | 午夜精品久久久久久久99无限制 | 久久免费中文视频 | 国产二区视频在线观看 | 国产一线二线三线在线观看 | 国产精品黄色影片导航在线观看 | 免费人成网ww44kk44 | 99久久精品国产系列 | 欧美精品在线观看 | 国产日本在线 | 超级碰碰碰免费视频 | 天天操天天是 | 国产一级片播放 | 精品国产伦一区二区三区 | 狠狠干电影 | 亚洲综合涩 | 亚洲视频电影在线 | 久久久久久久久久久影视 | 国产在线观看你懂得 | 国产精品1区2区在线观看 | 国产一区二区三精品久久久无广告 | 黄色影院在线免费观看 | 美女黄网久久 | av手机在线播放 | 久99久精品| 日韩精品久久久久久 | 国产精品一二三 | 久久99精品久久久久蜜臀 | 国产一卡在线 | 在线亚洲激情 | 99热官网| 五月婷婷伊人网 | 成人av片免费看 | 久久久久久电影 | 成人免费中文字幕 | 美女在线免费视频 | 国产精品成人国产乱 | 在线一二区 | a视频在线观看免费 | 热久久国产 | 日本久久精品视频 | 91成人黄色 | 欧美激情视频一二三区 | japanesexxxhd奶水| 日韩欧美一区二区三区免费观看 | 日韩精品视频在线免费观看 | 在线观看中文字幕dvd播放 | 黄色网址中文字幕 | 国语精品免费视频 | 成人性生交大片免费观看网站 | 国内精品视频久久 | 久久综合日 | 精品久久久久久亚洲综合网站 | 黄色片网站 | 久久伊人色综合 | 国产99久久久精品视频 | 中文字幕在线观看视频一区 | 深夜福利视频在线观看 | 91在线视频导航 | 在线一级片 | 黄色大全免费网站 | 久久久久久久免费观看 | 99久精品 | 日韩精品偷拍 | 久久久久久久久久国产精品 | 久久久久久久久久久久国产精品 | 在线观看韩国av | 国产麻豆精品一区 | 成人av网页| av在线网站大全 | 色婷五月 | 日韩视频在线不卡 | 九九视频在线播放 | 国产一区 在线播放 | 日日草夜夜操 | 韩国av在线播放 | 激情五月色播五月 | 欧美大片在线看免费观看 | 99精品久久久久久久 | 日韩黄色网络 | 激情综合网五月激情 | 在线观看国产日韩欧美 | 久久久久久国产精品久久 | 99爱这里只有精品 | 欧美一级电影免费观看 | av电影在线不卡 | 国产日本亚洲 | 国内三级在线观看 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 国产精品18久久久久白浆 | 欧美激情另类 | 少妇av网 | 久久久精品久久日韩一区综合 | 九九免费在线观看视频 | 国产糖心vlog在线观看 | 三级黄色网络 | 亚洲砖区区免费 | 中文在线免费视频 | 国产精品免费久久久久 | 午夜国产福利在线 | 精品在线99| av黄网站| 免费91在线观看 | 久久视频这里只有精品 | 69av在线视频 | 国产精品手机播放 | 国产在线看一区 | 亚洲一级片 | 国产亚洲激情视频在线 | 一级免费黄色 | 欧美片网站yy | 欧美日韩一区二区三区免费视频 | 免费黄a大片 | 99精品国产免费久久久久久下载 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 国产精品麻豆免费版 | 欧美巨乳网 | 亚洲国产免费 | 久久99精品久久久久久三级 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 伊人午夜视频 | 综合久久综合久久 | 国产高清绿奴videos | 国产精品久久久久久妇 | 久久午夜精品视频 | 免费裸体视频网 | 曰韩在线| 日韩一级电影在线 | 国产色视频网站 | 婷婷综合视频 | 在线看成人 | 午夜精品电影一区二区在线 | 国产精品一区在线观看你懂的 | 中文字幕av免费 | 久草在线中文视频 | 日韩一区精品 | 国产精品久久久久影院 | 国产精品嫩草55av | 国产午夜在线观看视频 | 久久夜色电影 | 免费观看黄 | 亚洲一区二区三区四区精品 | 99精品在线视频观看 | 中文字幕在线观看av | 欧洲高潮三级做爰 | 精品乱码一区二区三四区 | 亚洲日本三级 | 中文一区在线 | 97精品超碰一区二区三区 | 狠狠干夜夜操天天爽 | 日本久久成人中文字幕电影 | 久久精品艹 | 久久高清视频免费 | 久久久久久久免费 | 在线观看中文字幕dvd播放 | 欧美日韩99 | 九九爱免费视频在线观看 | 欧美一区二区三区四区夜夜大片 | 四虎在线免费视频 | 欧美成人va| 中文在线免费一区三区 | av网址在线播放 | 欧美日韩精品二区第二页 | 在线看欧美 | 久久久黄色av | 欧美精品网站 | 国产韩国日本高清视频 | 色窝资源 | www.av小说 | 人人艹视频 | 成人资源站 | 97国产情侣爱久久免费观看 | 91精品啪 | 中文字幕在线观看第二页 | 久久综合婷婷综合 | 亚洲色图27p| 日韩在线免费小视频 | av黄色成人 | 91成人在线免费观看 | 九九综合久久 | 在线观看www视频 | 四虎成人精品永久免费av九九 | 久久伊人五月天 | 六月天综合网 | 国产精品麻豆果冻传媒在线播放 | 久久精品视频播放 | www.久热| 国产精品18久久久久久vr | 亚洲精品国产精品国自产 | 国产午夜三级一二三区 | 在线观看免费成人av | 69性欧美| 亚洲一区二区三区毛片 | 夜夜操夜夜干 | 狠狠五月婷婷 | 六月婷色| 丁香婷婷激情啪啪 | 亚洲一区欧美激情 | 国产女人免费看a级丨片 | 青青草国产在线 | 国产精品久久久久国产精品日日 | 久久综合毛片 | 成人av直播| 国产一在线精品一区在线观看 | 深夜成人av| 日韩在线观看网址 | 国内精品久久久久国产 | 国产成人精品久久久久 | 97超碰.com | 欧美精品一二三 | 蜜臀aⅴ精品一区二区三区 久久视屏网 | 97在线观看免费 | 欧美成人va | 人人爱人人做人人爽 | 婷婷综合五月天 | 国产乱码精品一区二区三区介绍 | 最新国产福利 | 久久久久久久久久久电影 | 国产黄色特级片 | 国产精品99久久久久久久久久久久 | 日日干干| 日韩一区二区在线免费观看 | 婷婷色网视频在线播放 | 国产精品自拍在线 | 欧美另类tv| 天天天干天天射天天天操 | 久久精品国产免费观看 | 色综合天天爱 | 国产97在线看 | 黄色国产精品 | 97在线观看免费高清完整版在线观看 | 国产98色在线 | 日韩 | 成人香蕉视频 | 黄色毛片视频免费观看中文 | 亚洲国产影院av久久久久 | 久久成人久久 | 91激情视频在线播放 | 麻豆视频免费播放 | 久久久久久久综合色一本 | 日韩在线首页 | 精品视频一区在线 | 精品在线观看国产 | www.久久视频 | 欧美精品xx| 中文字幕在线观看网站 | 日韩黄色大片在线观看 | 中文字幕免费高清在线观看 | 97视频免费看 | 久久成年人视频 | 免费网址你懂的 | 久久国产热视频 | 97热视频 | 国产视频在线看 | 天天操天天摸天天爽 | 欧洲精品久久久久毛片完整版 | 激情片av | 欧美激情综合五月 | 91九色蝌蚪国产 | 久艹在线播放 | 亚洲精品456在线播放第一页 | 在线免费观看视频 | 久久福利在线 | 欧美九九九 | 国产涩涩在线观看 | 丁香激情综合国产 | 国产视频91在线 | 国产一区在线视频观看 | 亚洲黄网站 | 丁香六月中文字幕 | 在线免费观看视频一区二区三区 | 精品理论片| 亚洲精品一区二区精华 | 在线成人免费电影 | 国产精品久久在线 | 2019天天干天天色 | 狠狠躁日日躁狂躁夜夜躁av | 精品一区二区免费视频 | 日韩中文字幕视频在线观看 | 狠狠色噜噜狠狠狠狠2022 | 午夜美女福利直播 | 午夜视频色 | 天天干人人干 | 韩日三级av | 97国产在线观看 | 色av色av色av | 欧美另类亚洲 | av日韩不卡| 麻豆高清免费国产一区 | 天天插天天操天天干 | 久久久精华网 | 黄色一级动作片 | 亚洲无吗av | 久草在在线| 国产日韩在线一区 | 日本中文一区二区 | 特级西西人体444是什么意思 | 国产69精品久久99不卡的观看体验 | 亚洲 欧洲 国产 日本 综合 | 久视频在线播放 | 天天天射 | 国产亚洲精品成人av久久影院 | 午夜精品福利一区二区三区蜜桃 | 在线不卡a| 日韩亚洲欧美中文字幕 | 开心色停停 | 99 色| 日本深夜福利视频 | 91大神dom调教在线观看 | 亚洲国产操 | 国模视频一区二区三区 | 91视频免费看 | 亚洲成av人影院 | 香蕉视频日本 | 精品久久久久国产免费第一页 | 欧美最新大片在线看 | 日本中文字幕在线看 | 久久99热这里只有精品 | 欧美a性 | 亚洲欧美视频 | 久久影院亚洲 | 国产传媒中文字幕 | 日韩理论在线观看 | 国产99免费视频 | 国产黄色播放 | 色婷婷综合久久久久 | 欧美日韩不卡在线 | 亚洲精品66 | 91丨精品丨蝌蚪丨白丝jk | 国产精品成人av在线 | 爱爱一区| 久久久久久麻豆 | 成人av视屏 | 国产精品完整版 | 婷婷www | 久久综合九色综合欧美就去吻 | 91字幕 | 亚洲综合激情 | 中文字幕日韩国产 | 久久久久亚洲天堂 | 婷婷丁香色 | 亚洲精品视频一 | 国产成人免费高清 | 丝袜av一区 | 最新久久免费视频 | 国产成人av电影 | 欧美天天综合网 | 国产精品免费小视频 | 韩国精品在线观看 | 欧美一区二区伦理片 | 免费视频三区 | 免费国产在线精品 | 国产精品99久久久久久武松影视 | 超碰在线最新网址 | а天堂中文最新一区二区三区 | 96久久| 久久精品视频在线观看 | 在线免费视 | 国产99爱| 中文字幕永久 | 国产高清精品在线观看 | 国产精品av久久久久久无 | 亚洲精选在线观看 | 国产亚洲精品久久久久动 | 九九热免费在线视频 | 五月天欧美精品 | 综合色天天 | 午夜国产一区二区三区四区 | 免费看的黄色录像 | av三级在线免费观看 | 国产精品成人品 | 日韩精品在线播放 | 国产一级大片在线观看 | 国产精品入口麻豆www | 精品久久久久久综合日本 | 国内亚洲精品 | 99re8这里有精品热视频免费 | 欧美日韩一区二区三区免费视频 | 狠狠插狠狠干 | 日韩电影中文字幕在线观看 | 国产免费久久 | 日韩精品久久中文字幕 | 精品九九久久 | 成人av免费在线播放 | 黄色a一级片 | 亚洲精品av在线 | 九七视频在线观看 | 69久久久久久久 | 亚洲春色综合另类校园电影 | 欧美精品久久久久久久久久丰满 | 国产精品扒开做爽爽的视频 | 精品理论片 | 国产精品99蜜臀久久不卡二区 | 日韩三级视频在线看 | 91丨九色丨蝌蚪丨老版 | 美女视频黄免费网站 | 天天干天天干天天色 | 久久久精品国产一区二区三区 | 国产精品五月天 | 国产资源站 | 中文字幕在线国产精品 | 日韩精选在线 | 男女激情片在线观看 | 国产成人精品一区二区三区免费 | 天天操夜夜逼 | 免费看一级黄色 | 欧美精品一区二区三区一线天视频 | 亚洲三区在线 | www操操 | 色婷婷综合视频在线观看 | 天天天干夜夜夜操 | 99色亚洲 | 综合网天天色 | 九九热在线视频 | 亚洲国产欧美一区二区三区丁香婷 | 日韩免费观看一区二区三区 | 亚洲三级网 | 亚洲乱码一区 | 国产女教师精品久久av | 久久综合给合久久狠狠色 | 91九色蝌蚪视频网站 | 人人爽久久涩噜噜噜网站 | 手机av电影在线观看 | 欧美婷婷色 | 国产精品久久久久久久av大片 | 欧美一区二区三区特黄 | 9ⅰ精品久久久久久久久中文字幕 | 国产日韩在线播放 | 91精品一 | 久久久精品日本 | 日日操天天爽 | 国产手机在线观看视频 | 一色屋精品视频在线观看 | 亚洲h视频在线 | 久久亚洲在线 | 91麻豆精品国产91久久久无需广告 | 色视频一区| 麻花豆传媒mv在线观看 | 久久午夜网 | 一区二区三区在线观看中文字幕 | 成人av动漫在线 | 久久久高清免费视频 | 国产成人精品一区二区三区 | 久久久久欠精品国产毛片国产毛生 | 国产福利午夜 | 成人教育av | 九色精品免费永久在线 | 久久免费在线视频 | 久久久午夜剧场 | 久久视屏网 | 黄av免费在线观看 | 夜夜夜草 | 麻豆视频免费在线观看 | 亚洲一区 影院 | 精品国产乱码久久久久久三级人 | 狠狠干,狠狠操 | 日韩午夜三级 | 亚洲高清在线视频 | 欧美va日韩va | 国产在线观看午夜 | 国产成人久久精品77777综合 | 婷婷色网视频在线播放 | 在线看片a| 成人av电影免费 | 精品欧美乱码久久久久久 | 国产精品中文字幕在线观看 | 91视频在线网址 | 免费十分钟 | 黄a在线观看 | 免费成人av | 天天色天天射天天干 | av免费网站观看 | 黄色中文字幕在线 | 97碰在线视频| 国产一区二区在线播放视频 | 涩涩成人在线 | 啪啪免费试看 | 久久精品a | 丁香六月综合网 | 久久精品aaa| 特级黄色电影 | www.久久99 | 日韩在线在线 | 免费在线观看av网站 | 500部大龄熟乱视频使用方法 | 欧美日韩亚洲精品在线 | 夜夜躁日日躁狠狠久久88av | 狠狠的干狠狠的操 | 九九精品视频在线观看 | 成年人免费av| 国产成人免费av电影 | 国产看片 色 | 日韩午夜电影网 | 日韩av成人免费看 | 国产亚洲高清视频 | 美女免费视频一区 | 日韩精选在线观看 | 91成人精品一区在线播放69 | 国产成人一级 | 欧美 日韩 视频 | 天天av天天 | 日韩精品在线播放 | 亚州欧美视频 | 天天草天天干天天 | 4438全国亚洲精品观看视频 | 久久久久日本精品一区二区三区 | 91精品啪啪 | 免费在线播放视频 | 久久高清免费视频 | 国内精品毛片 | 爱情影院aqdy鲁丝片二区 | 在线国产一区二区三区 | 日韩在线看片 | 夜夜躁日日躁狠狠久久av | 中文字幕观看在线 | 九九九九九精品 | 国产最新精品视频 | 国产精品一区二区三区观看 | 天天色综合三 | 国产精品免费在线视频 | 国产精品久久久久久久av大片 | 91九色丨porny丨丰满6 | 成人黄色片在线播放 | 久久久人| 国产色视频网站2 | 色六月婷婷 | 国产一区二区网址 | 四虎伊人 | 九九99视频| 九九视频免费 | 欧美精品久久久久久久久免 | 天天操天天干天天摸 | 在线观看你懂的网址 | 国外调教视频网站 | 欧美成人影音 | 天天插天天射 | 黄色精品一区二区 | 日韩精品中文字幕在线播放 | 亚洲最新av网站 | 国产一级免费视频 | 亚洲精品自拍视频在线观看 | 九九热免费在线视频 | 亚洲精品在线观看中文字幕 | 日韩成人看片 | 999精品网| 国产精品久久久一区二区三区网站 | 亚洲黄电影| 久草在线免费新视频 | 女人18精品一区二区三区 | 欧美精品做受xxx性少妇 | 91成熟丰满女人少妇 | 三三级黄色片之日韩 | 婷婷在线免费视频 | 欧美日韩精品电影 | 欧美男同视频网站 | 国产做爰视频 | 色婷婷av一区二 | 国产精品手机播放 | 久久久久久久久久久精 | 中文字幕久久精品亚洲乱码 | 日韩 在线a | 色吊丝在线永久观看最新版本 | 欧美日韩视频一区二区三区 | 婷婷网站天天婷婷网站 | 免费精品久久久 | 久久久久免费视频 | 九九九在线观看 | 国产做aⅴ在线视频播放 | 在线观看av免费观看 | 最近中文字幕视频网 | 欧美先锋影音 | 成年人看片 | 亚一亚二国产专区 | 国产一级在线免费观看 | 欧美资源在线观看 | 在线免费观看黄色小说 | 天天干天天干天天干天天干天天干天天干 | 在线91网| 国产亚洲精品久久久久久久久久 | 国模视频一区二区三区 | 欧美乱淫视频 | 色婷婷免费视频 | 亚洲 欧美日韩 国产 中文 | 三级黄色网址 | 久久久久免费精品视频 | 一区二区激情视频 | 99在线观看精品 | 免费观看一级视频 | av一级黄| 国产专区在线视频 | 日韩视频三区 | 国产色资源 | 麻豆免费在线视频 | 久久久久亚洲精品成人网小说 | 日产乱码一二三区别免费 | 91丨九色丨国产在线 | 黄色性av | 综合久久精品 | 黄色免费网站大全 | 9992tv成人免费看片 | 国产91免费在线 | av成人免费观看 | 久久视频这里有精品 | 久久er99热精品一区二区三区 | 麻豆精品视频在线 | 成人激情开心网 | 97在线观看免费观看高清 | 九九热视频在线免费观看 | 久久不卡国产精品一区二区 | 九九久久电影 | 免费久久网 | 99视频99| 日韩一区二区三区高清免费看看 | 午夜手机电影 | 国产一区二区在线观看视频 | 视频国产在线观看18 | 国产一区二区久久久 | 中文字幕一区二区三区乱码不卡 | 精品不卡视频 | 亚洲小视频在线观看 | 日韩| 亚洲开心激情 | 色婷婷久久久综合中文字幕 | 国产精品免费久久久久久久久久中文 | 综合天天色| www.在线观看视频 | 一本之道乱码区 | 五月天丁香综合 | 亚洲精品国产综合99久久夜夜嗨 | 免费麻豆 | 丁香视频免费观看 | 在线观看视频日韩 | 久久在线免费视频 | 国产美女视频一区 | 久久久影院 | 久久公开免费视频 | 天天做天天看 | 中文字幕在线看视频 | 五月婷婷久 | 在线视频区 | 免费观看91视频大全 | 久久免费看 | 在线观看成人一级片 | 中文字幕亚洲欧美日韩2019 | 国产1区在线观看 | 国产精品大片免费观看 | 久章操 | 色综合久久精品 | 99久久久久 | 女人高潮一级片 | 91麻豆精品国产91久久久使用方法 | 国产精品久久久久久欧美 | 91在线区 | 国产尤物在线视频 | 奇米影视777四色米奇影院 | 国产白浆视频 | 国产视频1 | 国产精品18久久久久vr手机版特色 | 国产福利一区在线观看 | 欧美日韩一区二区视频在线观看 | 精品久久久久亚洲 | 欧美精品乱码久久久久 |