Tomcat源码解析:Container中的Pipeline和Valve

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26323323/article/details/84849612

前言:

    我们在上一篇博客 中分析了关于tomcat处理请求的全过程,在最后的时候交给了当前Engine的pipeline去处理。

    Engine.pipeline获取了first_valve,然后执行其invoke方法,即完成了请求的处理。

    那么这个Pipeline和Valve到底什么关系呢,valve.invoke()方法到底是如何执行的呢?在本篇博客中就来分析一下

1.org.apache.catalina.Pipeline

    具体源码如下:

// Interface describing a collection of Valves that should be executed
// in sequence when the <code>invoke()</code> method is invoked
public interface Pipeline {
    public Valve getBasic();
    public Valve getFirst();
    public Container getContainer();
    ...
}

    注释翻译过来就是:Pipeline是valve的一个集合,valve.invoke()方法的执行是顺序执行的,执行完当前之后就调用下一个valve.invoke()方法,直到执行到最后一个valve为止

2.org.apache.catalina.core.StandardPipeline

    Pipeline的默认实现类。具体内容如下:

public class StandardPipeline extends LifecycleBase implements Pipeline, Contained {
    // 默认的Valve,每一个Pipeline都有一个默认的valve
    protected Valve basic = null;

    // 所关联的容器,每一个Pipeline只关联一个具体的容器
    protected Container container = null;

    // 指向第一个valve,valve与valve的排列是链表式的
    protected Valve first = null;
       
    // 添加valve方法
    @Override
    public void addValve(Valve valve) {

        // Validate that we can add this Valve
        if (valve instanceof Contained)
            ((Contained) valve).setContainer(this.container);

        // Start the new component if necessary
        if (getState().isAvailable()) {
            if (valve instanceof Lifecycle) {
                try {
                    ((Lifecycle) valve).start();
                } catch (LifecycleException e) {
                    log.error("StandardPipeline.addValve: start: ", e);
                }
            }
        }

        // 仔细看下这个过程,如果first为null,说明当前valve是第一个添加进来的
        // 那么将当前valve置为first,然后下一个指向basic
        if (first == null) {
            first = valve;
            valve.setNext(basic);
        // 如果已经有first,则遍历整个valve链表,一直遍历到basic为止
        // 在basic之前添加该valve
        // 无论如何都保证了basic是整个pipeline为最后一个valve
        } else {
            Valve current = first;
            while (current != null) {
                if (current.getNext() == basic) {
                    current.setNext(valve);
                    valve.setNext(basic);
                    break;
                }
                current = current.getNext();
            }
        }

        container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
    }

    总结:我们可以通过addValve方法总结出pipeline中valve的排列规则

    整个是按照链表来排列的,顺序添加,第一个添加的valve放在first位置,第二个放在first后面...以此类推

    最后一个valve是固定的,默认就是basic,其他的valve都放在basic之前

3.Pipeline与Container的关系

    通过刚才StandardPipeline的源码,我们看到每一个Pipeline关联一个具体的Container,说明每一个Container(Service、Engine、Host、Context)等每一层次的容器都会有一个也是唯一一个具体的Pipeline。

    那么这个容器的Pipeline是什么时候创建的呢,什么时候关联上去的呢?我们以StandardContext为例:

public class StandardContext extends ContainerBase
        implements Context, NotificationEmitter {}

//ContainerBase
public abstract class ContainerBase extends LifecycleMBeanBase implements Container {

    // 可以看到,这里创建了pipeline
    protected final Pipeline pipeline = new StandardPipeline(this);
}

//StandardPipeline构造方法
    public StandardPipeline(Container container) {

        super();
        setContainer(container);

    }

    总结:通过上面的分析可以看到,pipeline是在StandardContext对象创建的时候就已经创建好了,默认实现为StandardPipeline,并且关联当前Container到Pipeline

4.org.apache.catalina.Valve    

    Valve是一个接口,源码如下:

/**
 * <p>A <b>Valve</b> is a request processing component associated with a
 * particular Container.  A series of Valves are generally associated with
 * each other into a Pipeline.  The detailed contract for a Valve is included
 * in the description of the <code>invoke()</code> method below.</p>
 */
public interface Valve {
    public Valve getNext();
    public void invoke(Request request, Response response) throws IOException, ServletException;
    ...   
}

    通过注释我们可以了解到:Valve是一个处理请求的组件;一系列的Valve关联起来组成一个Pipeline;真正的执行业务在invoke方法中;

    

5.Valve的实现类

    通过查看Valve的实现类,我们可以看到,其实现类有很多,重点是以下四个实现类

    可以看到每一层次的Container都有一个标准的Valve实现类

    通过名称我们可以确认,StandardContextValve是Context层的valve实现类;StandardWrapperValve是Servlet层的valve实现类。我们主要就来看下这两个valve的源码

    1)StandardContextValve

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardContext</code> container implementation.
 */
final class StandardContextValve extends ValveBase {
    @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {

        // 1.不允许直接访问WEB-INF、META-INF下的资源
        MessageBytes requestPathMB = request.getRequestPathMB();
        if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/META-INF"))
                || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        // 2.如果Servletwrapper为空则直接抛错
        Wrapper wrapper = request.getWrapper();
        if (wrapper == null || wrapper.isUnavailable()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        ...
        // 3.获取到Context下一层次,也就是Servlet层的pipeline,然后按顺序执行其invoke方法
        wrapper.getPipeline().getFirst().invoke(request, response);
    }
}

    总结:通过StandardContextValve的分析可以看到,其主要作用就是开启下一个层次容器的pipeline中valve链顺序执行

    2)StandardWrapperValve

/**
 * Valve that implements the default basic behavior for the
 * <code>StandardWrapper</code> container implementation.
 */
final class StandardWrapperValve extends ValveBase {
        @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        ...
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        Servlet servlet = null;
        Context context = (Context) wrapper.getParent();

        ...// 一堆的check

        // 1.获取Wrapper对应的Servlet
        try {
            if (!unavailable) {
                servlet = wrapper.allocate();
            }
        } catch (UnavailableException e) {
            ...
        } 
        
        MessageBytes requestPathMB = request.getRequestPathMB();
        DispatcherType dispatcherType = DispatcherType.REQUEST;
        if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
                requestPathMB);
        // 2.创建一个请求链,将filter和Servlet都包裹在其中
        ApplicationFilterChain filterChain =
                ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);

        // Call the filter chain for this request
        // NOTE: This also calls the servlet's service() method
        try {
            if ((servlet != null) && (filterChain != null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (request.isAsyncDispatching()) {
                            request.getAsyncContextInternal().doInternalDispatch();
                        } else {
                            // 3.执行该请求链
                            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 e) {
           ...
        } 

        // 释放chain
        if (filterChain != null) {
            filterChain.release();
        }
        ...
    }
   ...
}

// filterChain.doFilter(request.getRequest(),response.getResponse())执行请求链
@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.PrivilegedExceptionAction<Void>() {
                    @Override
                    public Void run()
                        throws ServletException, IOException {
                        // 真正执行请求的方法
                        internalDoFilter(req,res);
                        return null;
                    }
                }
            );
        } catch( PrivilegedActionException pe) {
            ...
        }
    } else {
        // 真正执行请求的方法
        internalDoFilter(request,response);
    }
}

// 业务执行
private void internalDoFilter(ServletRequest request,
                              ServletResponse response)
    throws IOException, ServletException {

    // Call the next filter if there is one
    // 1.执行下一个filter
    if (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 instance
    // 2.在最后执行servlet.service()方法
    try {
        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 point
        if ((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);
        }
    }
}

    总结:由上可知,我们真正的Servlet业务处理在Valve里处理了。

    再结合之前关于Web请求处理的源码分析,可以看出来

connector.getService().getContainer().getPipeline().getFirst().invoke(request, response)

    这句代码处理的就是获取到当前Engine的pipeline,然后依次执行其valve,再到后面会依次调用Host、Context的valve,并依次执行,最后执行到对应的Servlet.service()执行真正的业务处理

猜你喜欢

转载自blog.csdn.net/qq_26323323/article/details/84849612