当前位置: 首页 > news >正文

邯郸网站设计怎么申请沧州网站设计公司价格

邯郸网站设计怎么申请,沧州网站设计公司价格,广告网站建设公司,wordpress 文章版本在使用 Tomcat 的时候#xff0c;我们只需要在 Servlet 实现类中写我们的业务逻辑代码即可#xff0c;不需要管 Socket 连接、协议处理要怎么实现#xff0c;因为这部分作为不经常变动的部分#xff0c;被封装到了 Tomcat 中#xff0c;程序员只需要引入 Tomcat 中即可我们只需要在 Servlet 实现类中写我们的业务逻辑代码即可不需要管 Socket 连接、协议处理要怎么实现因为这部分作为不经常变动的部分被封装到了 Tomcat 中程序员只需要引入 Tomcat 中即可这也是面向对象编程的经典实践。 那么 Tomcat 中的一次请求都要经过哪些类的处理呢以及 Tomcat 在处理的时候做了哪些方面的考量和设计呢 Connector 我们知道Tomcat 中的 Connector 组件负责 Socket 连接的创建和管理以及网络字节流的传输。在 Connector 组件中有三个组件 Endpoint、Processor、Adapt。 Endpoint负责 ServerSocket 的创建和循环获取 Socket 连接Processor根据具体的协议解析字节流中的数据Adapt将 Tomcat Request 转换成 ServletRequest将 ServletResponse 转换成 Tomcat Response Tomcat 的设计者将 Endpoint 和 Processor 又做了一次封装将它们封装在 ProtocolHandler 中表示协议处理器。 从上面看请求会先在 Endpoint 对象中被接受然后在 Processor 中被解析最后通过 Adapt 转换后发送给 Servlet 容器。 Endpoint NioEndpoint#startInternal 生命周期方法在启动 Tomcat 的时候会调用 Server#start - Service.start - Connector.start - ProtocolHandler.start() - EndPoint.start() - Endpoint.startInternal() Override public void startInternal() throws Exception {if (!running) {running true;paused false;if (socketProperties.getProcessorCache() ! 0) {processorCache new SynchronizedStack(SynchronizedStack.DEFAULT_SIZE,socketProperties.getProcessorCache());}if (socketProperties.getEventCache() ! 0) {eventCache new SynchronizedStack(SynchronizedStack.DEFAULT_SIZE,socketProperties.getEventCache());}if (socketProperties.getBufferPool() ! 0) {nioChannels new SynchronizedStack(SynchronizedStack.DEFAULT_SIZE,socketProperties.getBufferPool());}// Create worker collectionif (getExecutor() null) {createExecutor();}initializeConnectionLatch();// Start poller thread// 启动一个 Poller 线程并赋值给 NioEndpoint 的 poller 成员变量// 这个变量在后续处理 PollerEvent 的时候会用到poller new Poller();Thread pollerThread new Thread(poller, getName() -Poller);pollerThread.setPriority(threadPriority);pollerThread.setDaemon(true);pollerThread.start();// 启动 Acceptor 线程startAcceptorThread();} }AbstractEndpoint#startAcceptorThread 创建并启动 Acceptor 线程 protected void startAcceptorThread() {acceptor new Acceptor(this);String threadName getName() -Acceptor;acceptor.setThreadName(threadName);Thread t new Thread(acceptor, threadName);t.setPriority(getAcceptorThreadPriority());t.setDaemon(getDaemon());t.start(); }Acceptor#run Acceptor 的 run 方法中循环获取 socket 连接为了减少篇幅和方便阅读我简化了代码 public void run() {int errorDelay 0;long pauseStart 0;try {// 循环直到我们接收到一个 shutdown 命令while (!stopCalled) {if (stopCalled) {break;}state AcceptorState.RUNNING;try {// 如果我们到达了最大连接数则阻塞该线程endpoint.countUpOrAwaitConnection();if (endpoint.isPaused()) {continue;}U socket null;try {// 获取 socket 连接socket endpoint.serverSocketAccept();} catch (Exception ioe) {...}// Successful accept, reset the error delayerrorDelay 0;if (!stopCalled !endpoint.isPaused()) {// setSocketOptions() 方法会把 socket 交给合适的 processor 处理if (!endpoint.setSocketOptions(socket)) {endpoint.closeSocket(socket);}} else {endpoint.destroySocket(socket);}} catch (Throwable t) {...}}} finally {stopLatch.countDown();}state AcceptorState.ENDED; }NioEndpoint#setSocketOptions 这里主要做了三件事 设置 socket 为非阻塞模式将 socket 封装到 NioSocketWrapper 中将 NioSocketWrapper 注册到 Poller 中 其中 NioSocketWrapper 是 NioEndpoint 的静态内部类Poller 是 NioEndpoint 的内部类它实现了 Runnable 接口。 Override protected boolean setSocketOptions(SocketChannel socket) {NioSocketWrapper socketWrapper null;try {// Allocate channel and wrapperNioChannel channel null;if (nioChannels ! null) {channel nioChannels.pop();}if (channel null) {SocketBufferHandler bufhandler new SocketBufferHandler(socketProperties.getAppReadBufSize(),socketProperties.getAppWriteBufSize(),socketProperties.getDirectBuffer());if (isSSLEnabled()) {channel new SecureNioChannel(bufhandler, this);} else {channel new NioChannel(bufhandler);}}// NioSocketWrapper 是 NioEndpoint 的静态内部类// 将 socket 封装到 NioSocketWrapper 中NioSocketWrapper newWrapper new NioSocketWrapper(channel, this);channel.reset(socket, newWrapper);connections.put(socket, newWrapper);socketWrapper newWrapper;// 设置 socket 为非阻塞模式socket.configureBlocking(false);socketProperties.setProperties(socket.socket());socketWrapper.setReadTimeout(getConnectionTimeout());socketWrapper.setWriteTimeout(getConnectionTimeout());socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());// Poller 是 NioEndpoint 的内部类它实现了 Runnable 接口poller.register(socketWrapper);return true;} catch (Throwable t) {...}// Tell to close the socket if neededreturn false; }Poller#register - Poller#addEvent 在 NioSocketWrapper 中设置感兴趣的事件是 SelectionKey.OP_READ也就是读事件此时还没有注册到 Selector 上将 NioSocketWrapper 封装成 PollerEvent并添加到 Poller 持有的同步队列中 /*** Registers a newly created socket with the poller.** param socketWrapper The socket wrapper*/ public void register(final NioSocketWrapper socketWrapper) {// 设置感兴趣的事件是读事件socketWrapper.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.// 将 NioSocketWrapper 封装成 PollerEventPollerEvent pollerEvent createPollerEvent(socketWrapper, OP_REGISTER);addEvent(pollerEvent); }private void addEvent(PollerEvent event) {// 将 PollerEvent 添加到 Poller 中 Tomcat 自定义的同步队列中events.offer(event);if (wakeupCounter.incrementAndGet() 0) {selector.wakeup();} }Poller#run Poller 线程在一个死循环中首先通过 events() 方法将 PollerEvent 同步队列中的 socket 用持有的 Selector 注册感兴趣的事件。 然后获取准备好的通道 每一个通道都传入 processKey 方法中 Override public void run() {// Loop until destroy() is calledwhile (true) {boolean hasEvents false;try {if (!close) {hasEvents events();if (wakeupCounter.getAndSet(-1) 0) {keyCount selector.selectNow();} else {keyCount selector.select(selectorTimeout);}wakeupCounter.set(0);}if (close) {events();timeout(0, false);try {selector.close();} catch (IOException ioe) {log.error(sm.getString(endpoint.nio.selectorCloseFail), ioe);}break;}// Either we timed out or we woke up, process events firstif (keyCount 0) {hasEvents (hasEvents | events());}} catch (Throwable x) {ExceptionUtils.handleThrowable(x);log.error(sm.getString(endpoint.nio.selectorLoopError), x);continue;}IteratorSelectionKey iterator keyCount 0 ? selector.selectedKeys().iterator() : null;// 如果 Selector 存在已经准备好的通道则遍历就绪的通道集while (iterator ! null iterator.hasNext()) {SelectionKey sk iterator.next();iterator.remove();NioSocketWrapper socketWrapper (NioSocketWrapper) sk.attachment();if (socketWrapper ! null) {processKey(sk, socketWrapper);}}// Process timeoutstimeout(keyCount,hasEvents);}getStopLatch().countDown(); }Poller#events public boolean events() {boolean result false;PollerEvent pe null;for (int i 0, size events.size(); i size (pe events.poll()) ! null; i ) {// 遍历存储 PollerEvent 的同步队列如果队列大于零则设置返回值 result 为 trueresult true;NioSocketWrapper socketWrapper pe.getSocketWrapper();SocketChannel sc socketWrapper.getSocket().getIOChannel();int interestOps pe.getInterestOps();if (sc null) {log.warn(sm.getString(endpoint.nio.nullSocketChannel));socketWrapper.close();} else if (interestOps OP_REGISTER) {try {sc.register(getSelector(), SelectionKey.OP_READ, socketWrapper);} catch (Exception x) {log.error(sm.getString(endpoint.nio.registerFail), x);}} else {// 当前 socketChannel 是否在 selector 中注册final SelectionKey key sc.keyFor(getSelector());if (key null) {socketWrapper.close();} else {final NioSocketWrapper attachment (NioSocketWrapper) key.attachment();if (attachment ! null) {try {int ops key.interestOps() | interestOps;attachment.interestOps(ops);// 在 selector 上注册 READ 事件每个 Poller 都会创建一个单独的 Selectorkey.interestOps(ops);} catch (CancelledKeyException ckx) {cancelledKey(key, socketWrapper);}} else {cancelledKey(key, socketWrapper);}}}if (running eventCache ! null) {// 重置 PollerEvent 并放回缓存 PollerEvent 的同步栈中pe.reset();eventCache.push(pe);}}return result; }Poller#processKey 该方法的核心逻辑是做条件判断通过判断 socket 准备好的事件的类型调用不同的方法来处理。如果是读事件最终会走到 processSocket(socketWrapper, SocketEvent.OPEN_READ, true) 。 protected void processKey(SelectionKey sk, NioSocketWrapper socketWrapper) {try {if (close) {cancelledKey(sk, socketWrapper);} else if (sk.isValid()) {if (sk.isReadable() || sk.isWritable()) {if (socketWrapper.getSendfileData() ! null) {processSendfile(sk, socketWrapper, false);} else {unreg(sk, socketWrapper, sk.readyOps());boolean closeSocket false;// Read goes before writeif (sk.isReadable()) {if (socketWrapper.readOperation ! null) {if (!socketWrapper.readOperation.process()) {closeSocket true;}} else if (socketWrapper.readBlocking) {synchronized (socketWrapper.readLock) {socketWrapper.readBlocking false;socketWrapper.readLock.notify();}} else if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) {closeSocket true;}}if (!closeSocket sk.isWritable()) {if (socketWrapper.writeOperation ! null) {if (!socketWrapper.writeOperation.process()) {closeSocket true;}} else if (socketWrapper.writeBlocking) {synchronized (socketWrapper.writeLock) {socketWrapper.writeBlocking false;socketWrapper.writeLock.notify();}} else if (!processSocket(socketWrapper, SocketEvent.OPEN_WRITE, true)) {closeSocket true;}}if (closeSocket) {cancelledKey(sk, socketWrapper);}}}} else {// Invalid keycancelledKey(sk, socketWrapper);}} catch (CancelledKeyException ckx) {cancelledKey(sk, socketWrapper);} catch (Throwable t) {ExceptionUtils.handleThrowable(t);log.error(sm.getString(endpoint.nio.keyProcessingError), t);} }Poller#processSocket 该方法用来将 NioSocketWrapper 封装到 SocketProcessor 中SocketProcessor 是 NioEndpoint 的内部类它实现了 Runnable 接口创建好 SocketProcessor 之后将它放到 executor 线程池中执行。 public boolean processSocket(SocketWrapperBaseS socketWrapper,SocketEvent event, boolean dispatch) {try {if (socketWrapper null) {return false;}SocketProcessorBaseS sc null;if (processorCache ! null) {sc processorCache.pop();}if (sc null) {sc createSocketProcessor(socketWrapper, event);} else {sc.reset(socketWrapper, event);}Executor executor getExecutor();if (dispatch executor ! null) {executor.execute(sc);} else {sc.run();}} catch (RejectedExecutionException ree) {getLog().warn(sm.getString(endpoint.executor.fail, socketWrapper) , ree);return false;} catch (Throwable t) {ExceptionUtils.handleThrowable(t);// This means we got an OOM or similar creating a thread, or that// the pool and its queue are fullgetLog().error(sm.getString(endpoint.process.fail), t);return false;}return true; }SocketProcessor#doRun 前面我们说过 Connector 组件中包含了 Endpoint、Processor 和 Adapt 三个组件三个组件各司其职完成了 Socket 客户端的连接、网络字节流的解析和 Request 和 Response 对象的转换。 在 SocketProcessor 线程会调用 Processor 组件的 process 方法来根据不同的协议解析字节流。 Override protected void doRun() {boolean launch false;try {SocketState state SocketState.OPEN;// Process the request from this socketif (event null) {state getHandler().process(socketWrapper, SocketEvent.OPEN_READ);} else {state getHandler().process(socketWrapper, event);}if (state SocketState.CLOSED) {// Close socket and poolsocketWrapper.close();} else if (state SocketState.UPGRADING) {launch true;}} catch (VirtualMachineError vme) {ExceptionUtils.handleThrowable(vme);} catch (Throwable t) {log.error(sm.getString(endpoint.processing.fail), t);if (socketWrapper ! null) {((Nio2SocketWrapper) socketWrapper).close();}} finally {...} }AbstractProtocol#process 调用 AbstractProcessLight 类的 process 方法 Override public SocketState process(SocketWrapperBaseS wrapper, SocketEvent status) {if (wrapper null) {// Nothing to do. Socket has been closed.return SocketState.CLOSED;}S socket wrapper.getSocket();Processor processor (Processor) wrapper.takeCurrentProcessor();try {...processor.setSslSupport(wrapper.getSslSupport(getProtocol().getClientCertProvider()));SocketState state SocketState.CLOSED;do {// 调用 AbstractProcessLight 类的 process 方法state processor.process(wrapper, status);...} while ( state SocketState.UPGRADING);...if (processor ! null) {wrapper.setCurrentProcessor(processor);}return state;} catch(java.net.SocketException e) {...}// Make sure socket/processor is removed from the list of current// connectionsrelease(processor);return SocketState.CLOSED; }AbstractProcessLight#process 该方法主要做一些条件判断如果我们的请求是一个简单的 GET 请求则会执行到 state service(socketWrapper); 这行代码。 Override public SocketState process(SocketWrapperBase? socketWrapper, SocketEvent status)throws IOException {SocketState state SocketState.CLOSED;IteratorDispatchType dispatches null;do {if (dispatches ! null) {DispatchType nextDispatch dispatches.next();if (getLog().isDebugEnabled()) {getLog().debug(Processing dispatch type: [ nextDispatch ]);}state dispatch(nextDispatch.getSocketStatus());if (!dispatches.hasNext()) {state checkForPipelinedData(state, socketWrapper);}} else if (status SocketEvent.DISCONNECT) {// Do nothing here, just wait for it to get recycled} else if (isAsync() || isUpgrade() || state SocketState.ASYNC_END) {state dispatch(status);state checkForPipelinedData(state, socketWrapper);} else if (status SocketEvent.OPEN_WRITE) {// Extra write event likely after async, ignorestate SocketState.LONG;} else if (status SocketEvent.OPEN_READ) {// 读事件state service(socketWrapper);} else if (status SocketEvent.CONNECT_FAIL) {logAccess(socketWrapper);} else {state SocketState.CLOSED;}...} while (state SocketState.ASYNC_END ||dispatches ! null state ! SocketState.CLOSED);return state; }Http11Processor#service Http11Processor 类是 HTTP/1.1 协议的实现这里会按照请求行、请求头、请求体的顺序解析字节流。 因为代码太多这里不做展示请求最终会调用 CoyoteAdapter#serviceCoyoteAdapter 是 Adapter 的实现类它属于 Connector 组件中的 Adapter 组件用于完成 Request 和 Response 对象的适配工作并调用 Container 的 Pipeline至此请求进入到 Servlet 容器中。 Override public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)throws Exception {Request request (Request) req.getNote(ADAPTER_NOTES);Response response (Response) res.getNote(ADAPTER_NOTES);...try {// Parse and set Catalina and configuration specific// request parameterspostParseSuccess postParseRequest(req, request, res, response);if (postParseSuccess) {//check valves if we support asyncrequest.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());// Calling the containerconnector.getService().getContainer().getPipeline().getFirst().invoke(request, response);}...} catch (IOException e) {// Ignore} finally {...} }总结 简单的梳理了 HTTP 请求进入 Tomcat 的代码调用栈之后我们可以通过上面的流程画出请求的流程图 Http11Processor 中主要是对 HTTP 协议的实现相比于这部分我对 Endpoint 中的处理更感兴趣因为这部分更接近操作系统这里我们只讨论了 Endpoint 在 NIO 模式下的处理流程在使用 NIO 模式的时候Tomcat 做了哪些设计和努力来让 Tomcat 能够支持高并发呢 随着 Tomcat 版本的不断更新每个版本都会对这部分做一些小优化该篇文章我用的 Tomcat 是 8.5.84 的版本其中 Endpoint 中的 Acceptor 和 Poller 都只开启了一个线程在之后的版本中改成了可以开启多个线程增加线程可以提高吞吐量。 Container 在上节讲解 Connector 组件的时候我们了解到Connector 最终会调用到 CoyoteAdapter#service 方法该方法会通过 Engine 的 Pipeline 将请求发送给 Servlet 容器。 CoyoteAdapter#service Override public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)throws Exception {...try {// Parse and set Catalina and configuration specific// request parameterspostParseSuccess postParseRequest(req, request, res, response);if (postParseSuccess) {//check valves if we support asyncrequest.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());// Calling the containerconnector.getService().getContainer().getPipeline().getFirst().invoke(request, response);}...} catch (IOException e) {// Ignore} finally {...} }在 Servlet 容器中组件被组织成具有层次结构大容器包小容器最小的容器就是 ServletEngine - Host - Context - Wrapper。每个容器组件都实现了 Container 接口且都持有 Pipeline 对象Pipeline 和 Valve 组合形成了责任链模式。 Pipeline 持有链路中第一个 First Valve 和最后一个 Basic Valve每个 Valve 持有下一个 Valve 的应用每个容器在初始化的时候会给 Pipeline 配置好 Basic Valve每个 Pipeline 的 Basic Valve 会调用子容器 Pipeline 的 First Valve于是请求就可以在容器中流转。 我们启动本地的 Tomcat并发起一个 GET 请求在 IDEA 中 debug 看在默认配置下各容器都持有哪些 Valve。 首先请求会到 StandardEngine可以看出持有的是 StandardPipeline它没有 First Valve只有 Basic Valve所以它只有一个 Valve在该 Valve 中完成请求的转发。 之后请求到 StandardHost它的 StandardPipeline 中既有 First Valve 也有 Basic ValvePipeline 中整个责任链如下 NonLoginAuthenticator StandardContextValve 之后请求到 StandardHost它的 StandardPipeline 也只有一个 Basic Valve。 最后是 StandardWrapper它的 StandardPipeline 也只有一个 Basic Valve。 StandardWrapperValve 有上可知StandardWrapperValve 应该是最后一个 Valve 了再之后就是 Servlet 了。这里单独拿出来细究是怎么到 Servlet 的 service 方法的。 Override public final void invoke(Request request, Response response)throws IOException, ServletException {...// Allocate a servlet instance to process this requesttry {if (!unavailable) {// 实例化 ServletServlet 是延迟实例化的只有用到了才会实例化在实例化的时候会调用 Servlet 的 init 方法servlet wrapper.allocate();}} catch (UnavailableException e) {...}...// Create the filter chain for this request// 为该请求创建 filterChainApplicationFilterChain filterChain ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);// Call the filter chain for this request// NOTE: This also calls the servlets service() methodContainer container this.container;try {if ((servlet ! null) (filterChain ! null)) {// Swallow output if neededif (context.getSwallowOutput()) {try {SystemLogHandler.startCapture();if (request.isAsyncDispatching()) {request.getAsyncContextInternal().doInternalDispatch();} else {// 触发过滤器链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 {// 触发过滤器链filterChain.doFilter(request.getRequest(), response.getResponse());}}}} catch (ClientAbortException | CloseNowException e) {...} finally {// 释放资源...} }由代码可知会先创建一个 filterChainservlet 就是在这里面被调用的我们继续看创建 filterChain 的方法。 public static ApplicationFilterChain createFilterChain(ServletRequest request,Wrapper wrapper, Servlet servlet) {// If there is no servlet to execute, return nullif (servlet null) {return null;}// Create and initialize a filter chain objectApplicationFilterChain filterChain null;if (request instanceof Request) {Request req (Request) request;if (Globals.IS_SECURITY_ENABLED) {// Security: Do not recyclefilterChain new ApplicationFilterChain();} else {filterChain (ApplicationFilterChain) req.getFilterChain();if (filterChain null) {filterChain new ApplicationFilterChain();req.setFilterChain(filterChain);}}} else {// Request dispatcher in usefilterChain new ApplicationFilterChain();}filterChain.setServlet(servlet);filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());// Acquire the filter mappings for this ContextStandardContext context (StandardContext) wrapper.getParent();FilterMap filterMaps[] context.findFilterMaps();// If there are no filter mappings, we are doneif ((filterMaps null) || (filterMaps.length 0)) {return filterChain;}// Acquire the information we will need to match filter mappingsDispatcherType 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 chainfor (FilterMap filterMap : filterMaps) {if (!matchDispatcher(filterMap, dispatcher)) {continue;}if (!matchFiltersURL(filterMap, requestPath)) {continue;}ApplicationFilterConfig filterConfig (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());if (filterConfig null) {// FIXME - log configuration problemcontinue;}filterChain.addFilter(filterConfig);}// Add filters that match on servlet name secondfor (FilterMap filterMap : filterMaps) {if (!matchDispatcher(filterMap, dispatcher)) {continue;}if (!matchFiltersServlet(filterMap, servletName)) {continue;}ApplicationFilterConfig filterConfig (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());if (filterConfig null) {// FIXME - log configuration problemcontinue;}filterChain.addFilter(filterConfig);}// Return the completed filter chainreturn filterChain; }通过 new 关键字创建 ApplicationFilterChain获取 Context 中所有的 Filter 实例并通过路径和 servlet name 筛选出匹配当前 Servlet 的 Filter 实例添加到 ApplicationFilterChain 中 创建成功后调用 filterChain.doFilter() 方法触发过滤器链。 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.PrivilegedExceptionActionVoid() {Overridepublic 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);} }private void internalDoFilter(ServletRequest request,ServletResponse response)throws IOException, ServletException {// Call the next filter if there is oneif (pos n) {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 {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);}} 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);}} }ApplicationFilterChain 中有一个 pos 变量来记录过滤器链执行位置执行每次从 Filter 数组 filters 中获取 Filter 后 pos 就加一。等到 Filter 被调用完之后会执行 servlet.service(request, response);。由此可见 Filter 是在 Servlet init 方法执行之后service 方法执行之前执行的。
http://www.dnsts.com.cn/news/110417.html

相关文章:

  • 做网站静态和动态淘宝店网站论坛怎么做
  • 网站开发团队名称上海小程序开发报价
  • 网站注册地址易加互动平台
  • 静态营销网站代码网站备案是每年一次吗
  • 自己服务器建网站 备案双井做网站的公司
  • 制作网站river免费wordpress主题下载
  • 网站建设公司价位h5网页版入口
  • 哪些网站做简历合适看p站用什么浏览器
  • 公司做网站 优帮云工程建设网最新信息网站
  • 吐鲁番好网站建设设计app线上推广是什么工作
  • 免版权图片网站龙岗成交型网站建设
  • 网站开发好要租服务器吗中国菲律宾数据
  • 杭州网站优化培训网站推广排名收费
  • 商城网站建设服务哪家好中职网站建设与维护考试题
  • 医美的网站主页怎么做聚宝汇 网站建设
  • 制作网站的页面设计怎么做电商平台哪个好
  • 网站的现状电子商务有限公司有哪些
  • 免费公司网站建设正在建设的网站可以随时进入吗
  • 企业网站建设相关书籍在线阅读郑州网站专业建设qq
  • 大连网站设计公司徐州网红有哪些人
  • 餐饮门户网站源码软件开发平台协议
  • 建设网站教程2016网站的引导页面是什么意思
  • 通辽市城乡建设局网站买衣服网站排名
  • 做设计找参考的设计网站有哪些建设网站步骤是
  • 天津知名网站建设公司苏州保洁公司哪家好
  • 各大网站开发语言企业邮箱使用方法
  • 建设网站申请文登住房和城乡建设局网站
  • 找做玻璃的网站桂林漓江风景区门票
  • 北京轨道交通建设公司网站制作微信公众号的软件
  • 现在有什么网站可以做兼职的wordpress 邮件配置