dubbo rest服务启动过程
dubbo作为rest服务,部署在tomcat容器启动过程分析。
web.xml 配置
<listener>
<listener-class>com.alibaba.dubbo.remoting.http.servlet.BootstrapListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
org.apache.dubbo.remoting.http.servlet.BootstrapListener
它的作用即将ServletContext保存下来,供后面使用
ServletContext
ServiceBean 启动
关于spring启动如何解析xml文件配置的spring bean请参考https://blog.csdn.net/zhurhyme/article/details/77650452
所以关于
DubboHttpServer启动
DubboHttpServer.start
-->BaseRestServer.start
-->BserRestServer.doStart
-->DubboHttpServer.doStart
DubboHttpServer部分源代码
package org.apache.dubbo.rpc.protocol.rest;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.remoting.http.HttpBinder;
import org.apache.dubbo.remoting.http.HttpHandler;
import org.apache.dubbo.remoting.http.HttpServer;
import org.apache.dubbo.remoting.http.servlet.BootstrapListener;
import org.apache.dubbo.remoting.http.servlet.ServletManager;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
import org.jboss.resteasy.spi.ResteasyDeployment;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
public class DubboHttpServer extends BaseRestServer {
private final HttpServletDispatcher dispatcher = new HttpServletDispatcher();
private final ResteasyDeployment deployment = new ResteasyDeployment();
private HttpBinder httpBinder;
private HttpServer httpServer;
// private boolean isExternalServer;
public DubboHttpServer(HttpBinder httpBinder) {
this.httpBinder = httpBinder;
}
@Override
protected void doStart(URL url) {
// TODO jetty will by default enable keepAlive so the xml config has no effect now
httpServer = httpBinder.bind(url, new RestHandler());
//获取servletContext参数
ServletContext servletContext = ServletManager.getInstance().getServletContext(url.getPort());
if (servletContext == null) {
servletContext = ServletManager.getInstance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT);
}
if (servletContext == null) {
throw new RpcException("No servlet context found. If you are using server='servlet', " +
"make sure that you've configured " + BootstrapListener.class.getName() + " in web.xml");
}
servletContext.setAttribute(ResteasyDeployment.class.getName(), deployment);
try {
dispatcher.init(new SimpleServletConfig(servletContext));//将servletContext传给resteasy dispatcher
} catch (ServletException e) {
throw new RpcException(e);
}
}
@Override
public void stop() {
httpServer.close();
}
@Override
protected ResteasyDeployment getDeployment() {
return deployment;
}
private class RestHandler implements HttpHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort());
dispatcher.service(request, response);
}
}
现在我们基本就清楚了,注意上面import的包路径。现在dubbo终于将将resteasy启动起来了。
resteasy 启动
对于resteasy启动,后期补上
请求过程
当一个请求过来,首先经过resteasy的部分我们先忽略。再次会被
DispatcherServlet.service(HttpServletRequest request, HttpServletResponse response)处理
它的源代码:
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpHandler handler = handlers.get(request.getLocalPort());
if (handler == null) {// service not found.
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Service not found.");
} else {
handler.handle(request, response);
}
}
将其转交给RestHandler,继而转交给HttpServletDispatcher(这里涉及到很多的设计模式,比如DispatherServlet、HttpServletDispatcher这两个类都是门面模式的典型使用方式)。