tomcat如何将请求分发到servlet
生活随笔
收集整理的這篇文章主要介紹了
tomcat如何将请求分发到servlet
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Tomcat對(duì)一個(gè)請(qǐng)求進(jìn)行解析時(shí),首先會(huì)進(jìn)行最首先的封裝,將請(qǐng)求封裝成Request對(duì)象。
之后在一個(gè)類(lèi)StandardWrapperValve中執(zhí)行invoke方法。 @Overridepublic final void invoke(Request request, Response response)throws IOException, ServletException {// Initialize local variables we may needboolean 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 unavailableif (!context.getState().isAvailable()) {response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,sm.getString("standardContext.isUnavailable"));unavailable = true;}// Check for the servlet being marked unavailableif (!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 requesttry {if (!unavailable) {servlet = wrapper.allocate(); //在可用情況下分配servlet,可用看看 unavailable變量的取值}} 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 requestApplicationFilterChain filterChain =ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); //重點(diǎn),創(chuàng)建filterChain,根據(jù)代碼實(shí)現(xiàn)的Filter// Call the filter chain for this request// NOTE: This also calls the servlet's service() methodtry {if ((servlet != null) && (filterChain != null)) {// Swallow output if neededif (context.getSwallowOutput()) { //swallowOutput 是Tomcat的Context的屬性,用于設(shè)置System.out是否輸出到日志,默認(rèn)falsetry {SystemLogHandler.startCapture();if (request.isAsyncDispatching()) {request.getAsyncContextInternal().doInternalDispatch();} else {filterChain.doFilter(request.getRequest(),response.getResponse()); //重點(diǎn),servlet和filter生效的地方}} finally {String log = SystemLogHandler.stopCapture();if (log != null && log.length() > 0) {context.getLogger().info(log);}}} else {if (request.isAsyncDispatching()) {request.getAsyncContextInternal().doInternalDispatch();} else {filterChain.doFilter(request.getRequest(), response.getResponse());//重點(diǎn),servlet和filter生效的地方}}}} catch (ClientAbortException e) { }........捕獲異常+后續(xù)內(nèi)存釋放等
@Overridepublic 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>() {@Overridepublic Void run()throws ServletException, IOException {internalDoFilter(req,res);//重點(diǎn)方法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;elsethrow new ServletException(e.getMessage(), e);}} else {internalDoFilter(request,response);//重點(diǎn)方法}}private void internalDoFilter(ServletRequest request,ServletResponse response)throws IOException, ServletException {// Call the next filter if there is oneif (pos < n) {//在 沒(méi)有循環(huán)完filter時(shí)循環(huán)調(diào)用doFilter方法,一個(gè)責(zé)任鏈模式的經(jīng)典實(shí)現(xiàn) 循環(huán)完跳出這個(gè)if方法塊 ApplicationFilterConfig filterConfig = filters[pos++];//獲取filterList由上面的createFilterChain創(chuàng)建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 {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 instancetry {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 pointif ((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 {servlet.service(request, response); //跳出循環(huán)后執(zhí)行此方法,進(jìn)入servlet的重點(diǎn)方法,對(duì)應(yīng)到spring就是DispatcherServlet }} 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);}}}l ine 14: 繼續(xù)調(diào)用
line 42,43: 責(zé)任鏈filter ?
line 98 :servlet的入口,對(duì)應(yīng)到spring就是DispatcherServlet?
之后在一個(gè)類(lèi)StandardWrapperValve中執(zhí)行invoke方法。 @Overridepublic final void invoke(Request request, Response response)throws IOException, ServletException {// Initialize local variables we may needboolean 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 unavailableif (!context.getState().isAvailable()) {response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,sm.getString("standardContext.isUnavailable"));unavailable = true;}// Check for the servlet being marked unavailableif (!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 requesttry {if (!unavailable) {servlet = wrapper.allocate(); //在可用情況下分配servlet,可用看看 unavailable變量的取值}} 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 requestApplicationFilterChain filterChain =ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); //重點(diǎn),創(chuàng)建filterChain,根據(jù)代碼實(shí)現(xiàn)的Filter// Call the filter chain for this request// NOTE: This also calls the servlet's service() methodtry {if ((servlet != null) && (filterChain != null)) {// Swallow output if neededif (context.getSwallowOutput()) { //swallowOutput 是Tomcat的Context的屬性,用于設(shè)置System.out是否輸出到日志,默認(rèn)falsetry {SystemLogHandler.startCapture();if (request.isAsyncDispatching()) {request.getAsyncContextInternal().doInternalDispatch();} else {filterChain.doFilter(request.getRequest(),response.getResponse()); //重點(diǎn),servlet和filter生效的地方}} finally {String log = SystemLogHandler.stopCapture();if (log != null && log.length() > 0) {context.getLogger().info(log);}}} else {if (request.isAsyncDispatching()) {request.getAsyncContextInternal().doInternalDispatch();} else {filterChain.doFilter(request.getRequest(), response.getResponse());//重點(diǎn),servlet和filter生效的地方}}}} catch (ClientAbortException e) { }........捕獲異常+后續(xù)內(nèi)存釋放等
line 43: ?//在可用情況下分配servlet,可用看看 unavailable變量的取值
line 82: ? //重點(diǎn),創(chuàng)建filterChain,根據(jù)代碼實(shí)現(xiàn)的Filter ?
line 89: ?swallowOutput 是Tomcat的Context的屬性,用于設(shè)置System.out是否輸出到日志,默認(rèn)false ?
line 96 97 110//重點(diǎn),servlet和filter生效的地方?
@Overridepublic 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>() {@Overridepublic Void run()throws ServletException, IOException {internalDoFilter(req,res);//重點(diǎn)方法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;elsethrow new ServletException(e.getMessage(), e);}} else {internalDoFilter(request,response);//重點(diǎn)方法}}private void internalDoFilter(ServletRequest request,ServletResponse response)throws IOException, ServletException {// Call the next filter if there is oneif (pos < n) {//在 沒(méi)有循環(huán)完filter時(shí)循環(huán)調(diào)用doFilter方法,一個(gè)責(zé)任鏈模式的經(jīng)典實(shí)現(xiàn) 循環(huán)完跳出這個(gè)if方法塊 ApplicationFilterConfig filterConfig = filters[pos++];//獲取filterList由上面的createFilterChain創(chuàng)建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 {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 instancetry {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 pointif ((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 {servlet.service(request, response); //跳出循環(huán)后執(zhí)行此方法,進(jìn)入servlet的重點(diǎn)方法,對(duì)應(yīng)到spring就是DispatcherServlet }} 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);}}}l ine 14: 繼續(xù)調(diào)用
line 42,43: 責(zé)任鏈filter ?
line 98 :servlet的入口,對(duì)應(yīng)到spring就是DispatcherServlet?
總結(jié)
以上是生活随笔為你收集整理的tomcat如何将请求分发到servlet的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: BUG总结——记一次sql查询未按照想要
- 下一篇: SpringMVC——Spring中的D