我们在上一篇博客 中分析了关于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 invoke()
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是一个接口,源码如下:
/**
* A Valve 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 invoke()
method below.
*/
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
* StandardContext
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
* StandardWrapper
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() {
@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()执行真正的业务处理