dubbo rest服务启动过程分析

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这两个类都是门面模式的典型使用方式)。

猜你喜欢

转载自blog.csdn.net/zhurhyme/article/details/81081295