赞
踩
版本:spring-boot-1.5.17.RELEASE.jar,jetty-servlet-9.4.41.v20210516.jar
springboot启动刷新上下文也是走的AbstractApplicationContext细节不再多说,我们直接进入正题,在onRefresh这个环节是springboot接入内嵌web容器的环节。在创建上下文时系统会判断当前是否是web环境,如果是则创建AnnotationConfigEmbeddedWebApplicationContext默认的web上下文。该上下文中的onRefresh环节进行创建内嵌的容器
新版本spring-boot-2.2.1.RELEASE : org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
@Override
protected void onRefresh() {
super.onRefresh();
try {
createEmbeddedServletContainer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start embedded container",
ex);
}
}
org.springframework.boot.web.servlet.ServletContextInitializer
EmbeddedWebApplicationContext.selfInitialize遍历ServletContextInitializer回调onStartup方法入参为ServletContext,与Servlet对接
@Override
public Iterator<ServletContextInitializer> iterator() {
//sortedList排序后的ServletRegistrationBean列表
return this.sortedList.iterator();
}
@Override public void onStartup(ServletContext servletContext) throws ServletException { Assert.notNull(this.servlet, "Servlet must not be null"); String name = getServletName(); ... logger.info("Mapping servlet: '" + name + "' to " + this.urlMappings); //注册至ServletContext上下文 Dynamic added = servletContext.addServlet(name, this.servlet); if (added == null) { logger.info("Servlet " + name + " was not registered " + "(possibly already registered?)"); return; } //配置servlet,urlMapping、setLoadOnStartup、setMultipartConfig configure(added); }
for (Connector connector : _connectors)
{
try
{
connector.start();
}
catch(Throwable e)
{
mex.add(e);
}
}
@Override
public void accept(int acceptorID) throws IOException
{
ServerSocketChannel serverChannel = _acceptChannel;
if (serverChannel != null && serverChannel.isOpen())
{
SocketChannel channel = serverChannel.accept();
accepted(channel);
}
}
//SelectorManager监听通道 public void accept(SelectableChannel channel, Object attachment) { ManagedSelector selector = this.chooseSelector(); Objects.requireNonNull(selector); //将ServerSocketChannel封装为Accept提交至updates,等待消费 selector.submit(new Accept(selector, channel, attachment)); } //SelectorManager容器管理初始化 protected SelectorManager(Executor executor, Scheduler scheduler, int selectors) { this._selectorIndex = new AtomicInteger(); this._acceptListeners = new ArrayList(); this._connectTimeout = 15000L; if (selectors <= 0) { //选择器默认数量 //如果线程池是SizedThreadPool类型:为cpu/2与线程池最大线程数/16之间的最小值 //否则cpu/2 selectors = defaultSelectors(executor); } this.executor = executor; this.scheduler = scheduler; this._selectors = new ManagedSelector[selectors]; //选择索引算法为index递增对长度取余即轮询方法 this._selectorIndexUpdate = (index) -> { return (index + 1) % this._selectors.length; }; } //容器管理的bean会在初始化管理器之后,启动管理选择器ManagedSelector,也是通过容器启动 protected void doStart() throws Exception { this._lease = ThreadPoolBudget.leaseFrom(this.getExecutor(), this, this._selectors.length); for(int i = 0; i < this._selectors.length; ++i) { ManagedSelector selector = this.newSelector(i); this._selectors[i] = selector; this.addBean(selector); } super.doStart(); }
//ManagedSelector提交监听的Accept对象至队列ArrayDeque public void submit(ManagedSelector.SelectorUpdate update) { ... Selector selector = null; synchronized(this) { this._updates.offer(update); //processUpdates处理之后将_selecting置为true开始唤醒selector的select阻塞 if (this._selecting) { selector = this._selector; this._selecting = false; } } if (selector != null) { ... //唤醒selector select阻塞 selector.wakeup(); } } //容器初始化时启动bean protected void doStart() throws Exception { super.doStart(); //调用选择管理器newSelector方法创建打开选择器Selector _selector = _selectorManager.newSelector(); // The producer used by the strategies will never // be idle (either produces a task or blocks). // The normal strategy obtains the produced task, schedules // a new thread to produce more, runs the task and then exits. //策略:EatWhatYouKill,通常为从不idle空闲,要么生产task,要么阻塞 _selectorManager.execute(_strategy::produce); // Set started only if we really are started Start start = new Start(); submit(start); start._started.await(); }
EatWhatYouKill不断的调用SelectorProducer执行生产方法返回的任务
将_updates队列中的SelectorUpdate数据封装的channel注册至指定的selector,并将当前channel与SelectionKey、Selector封装为相应的EndPoint对象(例如:SocketChannelEndPoint),将EndPoint绑定至SelectionKey的attachment
public void handleAsync(HttpChannel channel) throws IOException, ServletException { final HttpChannelState state = channel.getRequest().getHttpChannelState(); final AsyncContextEvent event = state.getAsyncContextEvent(); final Request baseRequest=channel.getRequest(); final String path=event.getPath(); if (path!=null) { // this is a dispatch with a path ServletContext context=event.getServletContext(); String query=baseRequest.getQueryString(); baseRequest.setURIPathQuery(URIUtil.addEncodedPaths(context==null?null:URIUtil.encodePath(context.getContextPath()), path)); HttpURI uri = baseRequest.getHttpURI(); baseRequest.setPathInfo(uri.getDecodedPath()); if (uri.getQuery()!=null) baseRequest.mergeQueryParameters(query,uri.getQuery(), true); //we have to assume dispatch path and query are UTF8 } final String target=baseRequest.getPathInfo(); final HttpServletRequest request=(HttpServletRequest)event.getSuppliedRequest(); final HttpServletResponse response=(HttpServletResponse)event.getSuppliedResponse(); ... handle(target, baseRequest, request, response); ... }
servlet(server applet)是web应用的一套接口标准,用于web应用的数据交换
后面再补充图片
/* * The state of the request processing lifecycle. * <pre> * BLOCKING <----> COMPLETING ---> COMPLETED * ^ | ^ ^ * / | \ | * | | DISPATCH | * | | ^ ^ | * | v / | | * | ASYNC -------> COMPLETE * | | | ^ * | v | | * | EXPIRE | | * \ | / | * \ v / | * EXPIRING ----------+ * </pre> */ private enum RequestState /* * The state of the HttpChannel,used to control the overall lifecycle. * <pre> * IDLE <-----> HANDLING ----> WAITING * | ^ / * | \ / * v \ v * UPGRADED WOKEN * </pre> */ public enum State
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。