緣起
大約3-4年前看過(guò) Tomcat 的源碼醋界,那時(shí)候主要聚焦在 Tomcat 加載 war 包的過(guò)程;一個(gè)星期前的周末在研究攔截器 Filter 的過(guò)程中發(fā)現(xiàn)可以整合Tomcat的執(zhí)行流程來(lái)一并分析膳帕,所以就有了這篇文章粘捎。
文章的輸出很大程度取決于日常的積累,時(shí)機(jī)到了就會(huì)有相應(yīng)的輸出危彩,基本上沒(méi)有其他更快的路徑了攒磨。
Tomcat 線程模型
Acceptor線程:全局唯一,負(fù)責(zé)接受請(qǐng)求汤徽,并將請(qǐng)求放入Poller線程的事件隊(duì)列娩缰。Accetpr線程在分發(fā)事件的時(shí)候,采用的Round Robin的方式來(lái)分發(fā)的
Poller線程:官方的建議是每個(gè)處理器配一個(gè)谒府,但不要超過(guò)兩個(gè)拼坎,由于現(xiàn)在幾乎都是多核處理器,所以一般來(lái)說(shuō)都是兩個(gè)狱掂。每個(gè)Poller線程各自維護(hù)一個(gè)事件隊(duì)列(無(wú)上限)演痒,它的職責(zé)是從事件隊(duì)列里面拿出socket,往自己的selector上注冊(cè)趋惨,然后等待selector選擇讀寫(xiě)事件鸟顺,并交給SocketProcessor線程去實(shí)際處理請(qǐng)求。
SocketProcessor線程池:tomcat的默認(rèn)配置是250(參見(jiàn)server.xml里面的maxThreads),它是實(shí)際的工作線程讯嫂,用于處理請(qǐng)求蹦锋。
Tomcat 執(zhí)行流程
Tomcat 監(jiān)聽(tīng)過(guò)程
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
private NioSelectorPool selectorPool = new NioSelectorPool();
private ServerSocketChannel serverSock = null;
private Executor executor = null;
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
@Override
public void bind() throws Exception {
// 創(chuàng)建 serverSock 執(zhí)行綁定
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
serverSock.socket().bind(addr,getAcceptCount());
serverSock.configureBlocking(true);
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
pollerThreadCount = 1;
}
setStopLatch(new CountDownLatch(pollerThreadCount));
initialiseSsl();
selectorPool.open();
}
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
// 創(chuàng)建 Poller 執(zhí)行任務(wù)的線程
if ( getExecutor() == null ) {
createExecutor();
}
initializeConnectionLatch();
// 開(kāi)啟 Poller 相關(guān)的線程
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
}
// 啟動(dòng)Acceptor線程
startAcceptorThreads();
}
}
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
public void createExecutor() {
internalExecutor = true;
TaskQueue taskqueue = new TaskQueue();
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
}
- Tomcat 監(jiān)聽(tīng)過(guò)程負(fù)責(zé)創(chuàng)建監(jiān)聽(tīng) socket 并進(jìn)行 bind 操作,參見(jiàn)bind()方法欧芽。
- Tomcat 負(fù)責(zé)創(chuàng)建Poller對(duì)象并綁定對(duì)應(yīng)的Poller線程莉掂。
- Tomcat 負(fù)責(zé)創(chuàng)建Acceptor對(duì)象并綁定對(duì)應(yīng)的Acceptor線程。
- Tomcat 負(fù)責(zé)創(chuàng)建SocketProcessor執(zhí)行的線程池對(duì)象 Executor千扔。
Tomcat 連接處理過(guò)程
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
private ServerSocketChannel serverSock = null;
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
while (running) {
// 省略相關(guān)代碼
state = AcceptorState.RUNNING;
try {
SocketChannel socket = null;
try {
// 獲取新的鏈接
socket = serverSock.accept();
} catch (IOException ioe) {
}
if (running && !paused) {
// 通過(guò)setSocketOptions設(shè)置新連接的socket
if (!setSocketOptions(socket)) {
closeSocket(socket);
}
}
} catch (Throwable t) {
}
}
state = AcceptorState.ENDED;
}
}
protected boolean setSocketOptions(SocketChannel socket) {
try {
socket.configureBlocking(false);
Socket sock = socket.socket();
socketProperties.setProperties(sock);
NioChannel channel = nioChannels.pop();
if (channel == null) {
SocketBufferHandler bufhandler = new SocketBufferHandler(
socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(),
socketProperties.getDirectBuffer());
if (isSSLEnabled()) {
channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
} else {
channel = new NioChannel(socket, bufhandler);
}
} else {
channel.setIOChannel(socket);
channel.reset();
}
// 注冊(cè)對(duì)應(yīng)的 Poller 當(dāng)中
getPoller0().register(channel);
} catch (Throwable t) {
return false;
}
return true;
}
public Poller getPoller0() {
int idx = Math.abs(pollerRotater.incrementAndGet()) % pollers.length;
return pollers[idx];
}
}
- Acceptor線程接受請(qǐng)求憎妙,從nioChannels里拿出NioChannel對(duì)象。從Poller 隊(duì)列中輪詢(xún)拿到一個(gè) Poller 后關(guān)聯(lián) NioChannel曲楚。
- setSocketOptions的getPoller0().register(channel)負(fù)責(zé)注冊(cè) accept 的NioChannel到Poller中厘唾。
Tomcat Socket 注冊(cè)過(guò)程
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
public class Poller implements Runnable {
private Selector selector;
private final SynchronizedQueue<PollerEvent> events =
new SynchronizedQueue<>();
private volatile boolean close = false;
private long nextExpiration = 0;
private AtomicLong wakeupCounter = new AtomicLong(0);
private volatile int keyCount = 0;
public Poller() throws IOException {
this.selector = Selector.open();
}
public void register(final NioChannel socket) {
socket.setPoller(this);
// 包裝 socket 成 NioSocketWrapper對(duì)象進(jìn)行處理
NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
socket.setSocketWrapper(ka);
ka.setPoller(this);
ka.setReadTimeout(getSocketProperties().getSoTimeout());
ka.setWriteTimeout(getSocketProperties().getSoTimeout());
ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
ka.setSecure(isSSLEnabled());
ka.setReadTimeout(getConnectionTimeout());
ka.setWriteTimeout(getConnectionTimeout());
PollerEvent r = eventCache.pop();
// 注意對(duì)應(yīng)的事件
ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
else r.reset(socket,ka,OP_REGISTER);
addEvent(r);
}
private void addEvent(PollerEvent event) {
events.offer(event);
if ( wakeupCounter.incrementAndGet() == 0 ) selector.wakeup();
}
public boolean events() {
boolean result = false;
PollerEvent pe = null;
while ( (pe = events.poll()) != null ) {
result = true;
try {
pe.run();
pe.reset();
if (running && !paused) {
eventCache.push(pe);
}
} catch ( Throwable x ) {
}
}
return result;
}
public void run() {
while (true) {
boolean hasEvents = false;
try {
if (!close) {
hasEvents = events();
}
} catch (Throwable x) {
}
// 省略代碼
}
}
}
public static class PollerEvent implements Runnable {
private NioChannel socket;
private int interestOps;
private NioSocketWrapper socketWrapper;
public PollerEvent(NioChannel ch, NioSocketWrapper w, int intOps) {
reset(ch, w, intOps);
}
@Override
public void run() {
if (interestOps == OP_REGISTER) {
try {
socket.getIOChannel().register(
socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper);
} catch (Exception x) {
}
}
}
}
}
- Poller實(shí)現(xiàn)NioChannel的register過(guò)程通過(guò)PollerEvent的創(chuàng)建和提交來(lái)實(shí)現(xiàn)。
- Poller的 run 方法中會(huì)調(diào)用PollerEvent的 run 方法龙誊,進(jìn)而實(shí)現(xiàn)NioChannel的注冊(cè)抚垃。
Tomcat Socket 任務(wù)處理過(guò)程
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
public class Poller implements Runnable {
@Override
public void run() {
while (true) {
// 省略代碼
Iterator<SelectionKey> iterator =
keyCount > 0 ? selector.selectedKeys().iterator() : null;
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
if (attachment == null) {
iterator.remove();
} else {
iterator.remove();
// 處理連接請(qǐng)求
processKey(sk, attachment);
}
}
timeout(keyCount,hasEvents);
}
}
protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
try {
if ( close ) {
cancelledKey(sk);
} else if ( sk.isValid() && attachment != null ) {
if (sk.isReadable() || sk.isWritable() ) {
if ( attachment.getSendfileData() != null ) {
processSendfile(sk,attachment, false);
} else {
unreg(sk, attachment, sk.readyOps());
boolean closeSocket = false;
if (sk.isReadable()) {
// 處理可讀事件
if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
closeSocket = true;
}
}
}
}
}
} catch (Throwable t) {
}
}
}
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
// SocketProcessor對(duì)象
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
Executor executor = getExecutor();
if (dispatch && executor != null) {
// 執(zhí)行對(duì)應(yīng)的連接請(qǐng)求
executor.execute(sc);
} else {
sc.run();
}
} catch (RejectedExecutionException ree) {
return false;
} catch (Throwable t) {
return false;
}
return true;
}
}
- Poller注冊(cè)NioChannel后通過(guò) select 方法返回待處理的NioSocketWrapper對(duì)象,進(jìn)而包裝成SocketProcessor后提交Executor 進(jìn)行處理趟大。
Tomcat 請(qǐng)求處理過(guò)程
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
protected class SocketProcessor extends SocketProcessorBase<NioChannel> {
public SocketProcessor(SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
super(socketWrapper, event);
}
@Override
protected void doRun() {
NioChannel socket = socketWrapper.getSocket();
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
try {
int handshake = -1;
// 省略代碼
if (handshake == 0) {
SocketState state = SocketState.OPEN;
// 通過(guò)ConnectionHandler 處理請(qǐng)求
if (event == null) {
state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
} else {
state = getHandler().process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
close(socket, key);
}
}
} catch (Throwable t) {
} finally {
}
}
}
}
- SocketProcessor作為封裝任務(wù)內(nèi)部?jī)H執(zhí)行ConnectionHandler的 proces 方法鹤树。
ConnectionHandler處理過(guò)程
public abstract class AbstractProtocol<S> implements ProtocolHandler,
MBeanRegistration {
protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
private final AbstractProtocol<S> proto;
private final RequestGroupInfo global = new RequestGroupInfo();
private final AtomicLong registerCount = new AtomicLong(0);
private final Map<S,Processor> connections = new ConcurrentHashMap<>();
private final RecycledProcessors recycledProcessors = new RecycledProcessors(this);
@Override
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
// 省略相關(guān)代碼
if (processor == null) {
processor = recycledProcessors.pop();
}
if (processor == null) {
processor = getProtocol().createProcessor();
register(processor);
}
do {
// 執(zhí)行Http11Processor的 process 方法
state = processor.process(wrapper, status);
} while ( state == SocketState.UPGRADING);
return state;
} catch (Throwable e) {
}
}
}
}
public abstract class AbstractHttp11Protocol<S> extends AbstractProtocol<S> {
@Override
protected Processor createProcessor() {
// 創(chuàng)建Http11Processor對(duì)象
Http11Processor processor = new Http11Processor(getMaxHttpHeaderSize(),
getAllowHostHeaderMismatch(), getRejectIllegalHeaderName(), getEndpoint(),
getMaxTrailerSize(), allowedTrailerHeaders, getMaxExtensionSize(),
getMaxSwallowSize(), httpUpgradeProtocols, getSendReasonPhrase());
// 省略相關(guān)代碼
return processor;
}
}
public class Http11Processor extends AbstractProcessor {
public Http11Processor(int maxHttpHeaderSize, boolean allowHostHeaderMismatch,
boolean rejectIllegalHeaderName, AbstractEndpoint<?> endpoint, int maxTrailerSize,
Set<String> allowedTrailerHeaders, int maxExtensionSize, int maxSwallowSize,
Map<String,UpgradeProtocol> httpUpgradeProtocols, boolean sendReasonPhrase) {
super(endpoint);
// 省略相關(guān)代碼
}
}
public abstract class AbstractProcessor extends AbstractProcessorLight implements ActionHook {
protected Adapter adapter;
protected final AsyncStateMachine asyncStateMachine;
private volatile long asyncTimeout = -1;
protected final AbstractEndpoint<?> endpoint;
protected final Request request;
protected final Response response;
protected volatile SocketWrapperBase<?> socketWrapper = null;
protected volatile SSLSupport sslSupport;
private ErrorState errorState = ErrorState.NONE;
public AbstractProcessor(AbstractEndpoint<?> endpoint) {
this(endpoint, new Request(), new Response());
}
protected AbstractProcessor(AbstractEndpoint<?> endpoint, Request coyoteRequest,
Response coyoteResponse) {
this.endpoint = endpoint;
asyncStateMachine = new AsyncStateMachine(this);
request = coyoteRequest;
response = coyoteResponse;
response.setHook(this);
request.setResponse(response);
request.setHook(this);
}
}
- ConnectionHandler通過(guò)Http11NioProtocol的createProcessor方法創(chuàng)建 Processor對(duì)象。通過(guò)recycledProcessors實(shí)現(xiàn)processor的重用性。
- Http11Processor作為processor 對(duì)象,內(nèi)部包含Request和Response對(duì)象嘲碧。
- Http11Processor的process方法負(fù)責(zé)處理請(qǐng)求邏輯羡洁。
- Http11Processor的重用意味著每次請(qǐng)來(lái)請(qǐng)求都要重置內(nèi)部Request和Response對(duì)象。
Http11Processor 處理過(guò)程
public abstract class AbstractProcessorLight implements Processor {
private Set<DispatchType> dispatches = new CopyOnWriteArraySet<>();
protected Adapter adapter;
// Http11Processor內(nèi)部包含Request 和 Response對(duì)象
protected final Request request;
protected final Response response;
@Override
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
throws IOException {
SocketState state = SocketState.CLOSED;
Iterator<DispatchType> dispatches = null;
do {
if (dispatches != null) {
} else if (status == SocketEvent.OPEN_READ){
// 執(zhí)行對(duì)應(yīng)的邏輯
state = service(socketWrapper);
}
// 省略相關(guān)代碼
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);
return state;
}
}
public abstract class AbstractProcessor
extends AbstractProcessorLight implements ActionHook {
protected Adapter adapter;
private volatile long asyncTimeout = -1;
protected final AbstractEndpoint<?> endpoint;
protected final Request request;
protected final Response response;
protected volatile SocketWrapperBase<?> socketWrapper = null;
}
public class Http11Processor extends AbstractProcessor {
@Override
public SocketState service(SocketWrapperBase<?> socketWrapper)
throws IOException {
// 省略相關(guān)代碼
while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&
sendfileState == SendfileState.DONE && !endpoint.isPaused()) {
try {
// 解析請(qǐng)求
if (!inputBuffer.parseRequestLine(keptAlive)) {
if (inputBuffer.getParsingRequestLinePhase() == -1) {
return SocketState.UPGRADING;
} else if (handleIncompleteRequestLineRead()) {
break;
}
}
} catch (Throwable t) {
}
// 解析 Request 對(duì)象
if (!getErrorState().isError()) {
try {
prepareRequest();
} catch (Throwable t) {
}
}
if (!getErrorState().isError()) {
try {
getAdapter().service(request, response);
} catch (Throwable t) {
}
}
sendfileState = processSendfile(socketWrapper);
}
}
}
- Http11Processor對(duì)象能夠被重用,每次處理請(qǐng)求都會(huì)重新初始化Request對(duì)象。
- Http11Processor處理每次請(qǐng)求通過(guò)inputBuffer.parseRequestLine和prepareRequest來(lái)重新初始化Request對(duì)象。
- Http11Processor的 service 內(nèi)部調(diào)用CoyoteAdapter的service方法湿酸。
CoyoteAdapter 執(zhí)行流程
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
// 5、StandardWrapperValve
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
// 4灭美、StandardContextValve
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
// 3推溃、StandardHostValve
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
// 2、StandardEngineValve
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
// 1届腐、CoyoteAdapter
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
- locked <0x19b6> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
- CoyoteAdapter的執(zhí)行流程按照 Tomcat 內(nèi)部對(duì)象的經(jīng)典順序進(jìn)行執(zhí)行铁坎,見(jiàn)調(diào)用棧注釋。
- 整個(gè)執(zhí)行過(guò)程最終調(diào)用的是StandardWrapperValve的 invoke 方法犁苏。
Tomcat Filter職責(zé)鏈
final class StandardWrapperValve
extends ValveBase {
public StandardWrapperValve() {
super(true);
}
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
Servlet servlet = null;
try {
if (!unavailable) {
// wrapper是StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper
// 創(chuàng)建一個(gè) servlet 對(duì)象
servlet = wrapper.allocate();
}
} catch (Throwable e) {
}
// 創(chuàng)建過(guò)濾器職責(zé)鏈
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
try {
if ((servlet != null) && (filterChain != null)) {
if (context.getSwallowOutput()) {
// 省略代碼
} else {
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
// 通過(guò)職責(zé)鏈開(kāi)始執(zhí)行
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
} catch (Throwable e) {
}
// 釋放職責(zé)鏈硬萍,職責(zé)鏈的釋放表示所有的filter 設(shè)置為 null
if (filterChain != null) {
filterChain.release();
}
// 回收 servlet 對(duì)象
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
}
}
public HttpServletResponse getResponse() {
if (facade == null) {
facade = new ResponseFacade(this);
}
if (applicationResponse == null) {
applicationResponse = facade;
}
return applicationResponse;
}
public HttpServletRequest getRequest() {
if (facade == null) {
facade = new RequestFacade(this);
}
if (applicationRequest == null) {
applicationRequest = facade;
}
return applicationRequest;
}
}
- StandardWrapperValve負(fù)責(zé)創(chuàng)建經(jīng)典的 servlet 對(duì)象,通過(guò)wrapper.allocate創(chuàng)建围详,內(nèi)部實(shí)現(xiàn)了 servlet 的單例模式朴乖。
- StandardWrapperValve負(fù)責(zé)創(chuàng)建 FilterChain 對(duì)象祖屏,通過(guò)createFilterChain方法。
- filterChain.doFilter方法中的request.getRequest()和response.getResponse()負(fù)責(zé)將 request 對(duì)象轉(zhuǎn)換成RequestFacade對(duì)象买羞,將 response 對(duì)象轉(zhuǎn)換成ResponseFacade對(duì)象袁勺。
Tomcat FilterChain創(chuàng)建和釋放
public final class ApplicationFilterChain implements FilterChain {
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
private int pos = 0;
private int n = 0;
public static final int INCREMENT = 10;
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
private Servlet servlet = null;
}
public final class ApplicationFilterFactory {
public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) {
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request) request;
if (Globals.IS_SECURITY_ENABLED) {
filterChain = new ApplicationFilterChain();
} else {
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
} else {
filterChain = new ApplicationFilterChain();
}
// 設(shè)置職責(zé)鏈的filterChain內(nèi)部的 sevlet 對(duì)象
filterChain.setServlet(servlet);
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();
if ((filterMaps == null) || (filterMaps.length == 0))
return (filterChain);
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
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
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) {
continue;
}
filterChain.addFilter(filterConfig);
}
return filterChain;
}
void addFilter(ApplicationFilterConfig filterConfig) {
for(ApplicationFilterConfig filter:filters)
if(filter==filterConfig)
return;
if (n == filters.length) {
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
void release() {
for (int i = 0; i < n; i++) {
filters[i] = null;
}
n = 0;
pos = 0;
servlet = null;
servletSupportsAsync = false;
}
}
- FilterChain內(nèi)部包含ApplicationFilterConfig數(shù)組保存Filter 對(duì)象。
- FilterChain每次請(qǐng)求開(kāi)始的時(shí)候進(jìn)行創(chuàng)建畜普,結(jié)束的時(shí)候負(fù)責(zé)回收(參考release方法)期丰。
Tomcat FilterChain的執(zhí)行
public final class ApplicationFilterChain implements FilterChain {
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
private int pos = 0;
private int n = 0;
public static final int INCREMENT = 10;
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
private Servlet servlet = null;
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
// 省略相關(guān)代碼
} else {
internalDoFilter(request,response);
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// 執(zhí)行職責(zé)鏈
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if( Globals.IS_SECURITY_ENABLED ) {
// 省略代碼
} else {
filter.doFilter(request, response, this);
}
} catch (Throwable e) {
}
return;
}
// 執(zhí)行 servlet 本身的服務(wù)
try {
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
// 省略相關(guān)代碼
} else {
// 執(zhí)行 serlvet 的服務(wù),默認(rèn)是DispatcherServlet對(duì)象
servlet.service(request, response);
}
} catch (Throwable e) {
} finally {
}
}
}
- 職責(zé)鏈的執(zhí)行有兩種視角吃挑,一種是以上帝視角外部調(diào)用 for 循環(huán)執(zhí)行钝荡,一種是每個(gè) Filter 自驅(qū)執(zhí)行并觸發(fā)下一個(gè) Filter,F(xiàn)ilterChain選擇的是后者儒鹿。
- FilterChain的執(zhí)行內(nèi)部通過(guò) pos 和 n 的位置標(biāo)記判斷是否執(zhí)行結(jié)束化撕。
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("time filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("time filter start");
long startTime = System.currentTimeMillis();
// filter內(nèi)部需要調(diào)用filterChain繼續(xù)執(zhí)行下一個(gè)Filter
filterChain.doFilter(servletRequest, servletResponse);
long endTime = System.currentTimeMillis();
System.out.println("time filter consume " + (endTime - startTime) + " ms");
System.out.println("time filter end");
}
}
- Tomcat 的 Filter 是通過(guò) filter 對(duì)象內(nèi)部執(zhí)行filterChain.doFilter來(lái)驅(qū)動(dòng)下一個(gè)Filter對(duì)象的執(zhí)行。
Tomcat Servlet 的創(chuàng)建
public class StandardWrapper extends ContainerBase
implements ServletConfig, Wrapper, NotificationEmitter {
@Override
public Servlet allocate() throws ServletException {
boolean newInstance = false;
// singleThreadModel = false
if (!singleThreadModel) {
// instance = DispatcherServlet
if (instance == null || !instanceInitialized) {
synchronized (this) {
if (instance == null) {
try {
instance = loadServlet();
newInstance = true;
if (!singleThreadModel) {
countAllocated.incrementAndGet();
}
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
}
}
if (!instanceInitialized) {
initServlet(instance);
}
}
}
if (singleThreadModel) {
if (newInstance) {
synchronized (instancePool) {
instancePool.push(instance);
nInstances++;
}
}
} else {
if (!newInstance) {
countAllocated.incrementAndGet();
}
// 最終返回的單例
return instance;
}
}
synchronized (instancePool) {
while (countAllocated.get() >= nInstances) {
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
} catch (Throwable e) {
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
countAllocated.incrementAndGet();
return instancePool.pop();
}
}
}
- Servlet屬于單例實(shí)例约炎。
Spring的DispatcherServlet
public abstract class HttpServlet extends GenericServlet {
private static final long serialVersionUID = 1L;
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified";
private static final String LSTRING_FILE =
"javax.servlet.http.LocalStrings";
private static final ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE);
public HttpServlet() {
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
}
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
protected void doDelete(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request; // RequestFacade
HttpServletResponse response; // ResponseFacade
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
}
public abstract class HttpServlet extends GenericServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
}
}
}
- DispatcherServlet內(nèi)部通過(guò) method 區(qū)分不同的邏輯執(zhí)行。
public class DispatcherServlet extends FrameworkServlet {
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 省略代碼
try {
this.doDispatch(request, response);
} finally {
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest);
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
// ha = RequestMappingHandlerAdapter蟹瘾,對(duì)應(yīng)的執(zhí)行對(duì)象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
} catch (Throwable var21) {
}
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
} catch (Throwable var23) {
}
} finally {
}
}
}
- DispatcherServlet的doDispatch通過(guò)對(duì)應(yīng)的mappedHandler執(zhí)行對(duì)應(yīng)的邏輯
public class InvocableHandlerMethod extends HandlerMethod {
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
catch (Exception ex) {
}
}
}
return args;
}
}
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
private final List<HandlerMethodArgumentResolver> argumentResolvers =
new LinkedList<HandlerMethodArgumentResolver>();
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
new ConcurrentHashMap<MethodParameter, HandlerMethodArgumentResolver>(256);
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
}
- DispatcherServlet通過(guò)InvocableHandlerMethod類(lèi)實(shí)現(xiàn)不同協(xié)議對(duì)應(yīng)的請(qǐng)求參數(shù)的解析圾浅。