StandardWrapperValue
StandardWrapperValue是Wrapper的标准阀,用在Pipleline流程中的最后一个valve执行。当Request请求到达Context的时候,继续传递给Wrapper,首先是调用StandardWrapper的Invoke方法(ContainerBase父类中),如下.
public void invoke(Request request, Response response)
throws IOException, ServletException {
pipeline.invoke(request, response);
}
pipeline就是与容器关联的一系列处理流程,StandardWrapperValve在初始化的时候就被加入到了pipeline中。而下面调用的pipeline的invoke方法,就是调用里面的各种Valve的invoke方法。
package tomcat.p4.core;
import java.util.Map;
import tomcat.p4.Pipline;
import tomcat.p4.PiplineContext;
import tomcat.p4.Valve;
/**
* 一个基本的pipline实现
* @author zhoufeng
*/
public class SimplePipline implements Pipline{
/**
* 阀门列表(相当于一系列的Filter)
*/
private Valve[] valves = new Valve[0];
/**
* 最终要执行的内容
*/
private Valve basic ;
@Override
public void setBasic(Valve basic) {
this.basic = basic ;
}
/**
* 添加一个阀
*/
@Override
public void addValve(Valve valve) {
Valve[] newValves = new Valve[valves.length + 1];
System.arraycopy(valves, 0, newValves, 0, valves.length);
newValves[newValves.length - 1] = valve ;
valves = newValves ;
}
/**
* 执行管道中的内容(注意这里使用内部类实例SimplePiplineContext实现)
*/
@Override
public void invoke(Map<String, Object> params) {
new SimplePiplineContext().invokeNext(params);
}
/**
* 这里使用一个私有的内部类实现PiplineContext,用于线性的依次执行pipline中的valves,然后执行basic
* @author zhoufeng
*
*/
private class SimplePiplineContext implements PiplineContext{
/**
* 记录当前正在执行到哪个valve
*/
private int step = 0 ;
@Override
public void invokeNext(Map<String, Object> params) {
int curStep = step ;
step++;
if(curStep < valves.length){
valves[curStep].invoke(params , this);
}else if(curStep == valves.length){
if(SimplePipline.this.basic != null){
SimplePipline.this.basic.invoke(params, this);
}
}else{
throw new RuntimeException("no valve fond");
}
}
}
}
下面就是StandedWrapperValve的核心逻辑,invoke方法:
public void invoke(Request request, Response response,
ValveContext valveContext)
throws IOException, ServletException {
// Initialize local variables we may need
boolean unavailable = false;
Throwable throwable = null;
StandardWrapper wrapper = (StandardWrapper) getContainer();
ServletRequest sreq = request.getRequest();
ServletResponse sres = response.getResponse();
Servlet servlet = null;
HttpServletRequest hreq = null;
if (sreq instanceof HttpServletRequest)
hreq = (HttpServletRequest) sreq;
HttpServletResponse hres = null;
if (sres instanceof HttpServletResponse)
hres = (HttpServletResponse) sres;
// Check for the application being marked unavailable
if (!((Context) wrapper.getParent()).getAvailable()) {
//503
hres.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardContext.isUnavailable"));
unavailable = true;
}
// Check for the servlet being marked unavailable
if (!unavailable && wrapper.isUnavailable()) {
log(sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
if (hres == null) {
; // NOTE - Not much we can do generically
} else {
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE))
hres.setDateHeader("Retry-After", available);
hres.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
}
unavailable = true;
}
// Allocate a servlet instance to process this request
try {
if (!unavailable) {
//通过Wrapper获取Servlet实例,内部已经调用了service(request, response)方法,对req与res进行了字段赋值
//下面是对Response和Request进行后续的处理
servlet = wrapper.allocate();
}
} catch (ServletException e) {
log(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
} catch (Throwable e) {
log(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
// Acknowlege the request
try {
response.sendAcknowledgement();
} catch (IOException e) {
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
log(sm.getString("standardWrapper.acknowledgeException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
log(sm.getString("standardWrapper.acknowledgeException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
// Create the filter chain for this request
// 创建对于Request与Response的过滤链
ApplicationFilterChain filterChain =
createFilterChain(request, servlet);
// Call the filter chain for this request
// NOTE: This also calls the servlet's service() method
try {
String jspFile = wrapper.getJspFile();
if (jspFile != null)
sreq.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
else
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
if ((servlet != null) && (filterChain != null)) {
//使用过滤链过滤Request与Response
filterChain.doFilter(sreq, sres);
}
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
} catch (IOException e) {
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
log(sm.getString("standardWrapper.serviceException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
log(sm.getString("standardWrapper.serviceException",
wrapper.getName()), e);
wrapper.unavailable(e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE))
hres.setDateHeader("Retry-After", available);
hres.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
// Do not save exception in 'throwable', because we
// do not want to do exception(request, response, e) processing
} catch (ServletException e) {
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
log(sm.getString("standardWrapper.serviceException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
log(sm.getString("standardWrapper.serviceException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
}
// Release the filter chain (if any) for this request
try {
if (filterChain != null)
//释放过滤链
filterChain.release();
} catch (Throwable e) {
log(sm.getString("standardWrapper.releaseFilters",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
//释放servlet
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
log(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
// If this servlet has been marked permanently unavailable,
// unload it and release this instance
try {
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
//回收所有的Servlet
wrapper.unload();
}
} catch (Throwable e) {
log(sm.getString("standardWrapper.unloadException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
}
StandardWrapper 的 allocate 方法 -- 实例化Servlet
public Servlet allocate() throws ServletException {
if (debug >= 1)
log("Allocating an instance");
// If we are currently unloading this servlet, throw an exception
if (unloading)
throw new ServletException
(sm.getString("standardWrapper.unloading", getName()));
// If not SingleThreadedModel, return the same instance every time
if (!singleThreadModel) {
// Load and initialize our instance if necessary
if (instance == null) {
synchronized (this) {
if (instance == null) {
try {
//加载Servlet
instance = loadServlet();
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException
(sm.getString("standardWrapper.allocate"), e);
}
}
}
}
//如果不是 SingleThreadModel 只会存在一个实例,所以直接返回唯一的实例就行
//SingleThreadModel 表示同一个对象在同一时刻只能被一个线程访问,所以会创建多个对象来处理多线程。这里会用对象池来管理对象
if (!singleThreadModel) {
if (debug >= 2)
log(" Returning non-STM instance");
countAllocated++;
return (instance);
}
}
synchronized (instancePool) {
//活动数量大于实例数量,要一直创建新的 Servlet 对象
//注意这个活动数量不是 Servlet 的数量,应该是活动线程的数量
while (countAllocated >= nInstances) {
// Allocate a new instance if possible, or else wait
if (nInstances < maxInstances) {
//如果实例数量小于最大实例数量,创建新的 Servlet 对象
//注意这里最大数量默认 20
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException
(sm.getString("standardWrapper.allocate"), e);
}
} else {
//如果实例数量达到最大数量,等待其它 Servlet 结束
try {
instancePool.wait();
} catch (InterruptedException e) {
;
}
}
}
if (debug >= 2)
log(" Returning allocated STM instance");
//如果活动线程数量小于实例数量,表示有空闲的 Servlet 对象来处理活动线程
//这里直接返回空闲的 Servlet 对象
countAllocated++;
return (Servlet) instancePool.pop();
}
}
StandardWrapper 的 loadServlet 方法
public synchronized Servlet loadServlet() throws ServletException {
// Nothing to do if we already have an instance or an instance pool
if (!singleThreadModel && (instance != null))
return instance;
PrintStream out = System.out;
SystemLogHandler.startCapture();
Servlet servlet = null;
try {
// If this "servlet" is really a JSP file, get the right class.
// HOLD YOUR NOSE - this is a kludge that avoids having to do special
// case Catalina-specific code in Jasper - it also requires that the
// servlet path be replaced by the <jsp-file> element content in
// order to be completely effective
//获取servlet类的全路径
String actualClass = servletClass;
if ((actualClass == null) && (jspFile != null)) {
Wrapper jspWrapper = (Wrapper)
((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
if (jspWrapper != null)
actualClass = jspWrapper.getServletClass();
}
// Complain if no servlet class has been specified
if (actualClass == null) {
unavailable(null);
throw new ServletException
(sm.getString("standardWrapper.notClass", getName()));
}
// Acquire an instance of the class loader to be used
//获取加载器
Loader loader = getLoader();
if (loader == null) {
unavailable(null);
throw new ServletException
(sm.getString("standardWrapper.missingLoader", getName()));
}
//获取类加载器
ClassLoader classLoader = loader.getClassLoader();
// Special case class loader for a container provided servlet
if (isContainerProvidedServlet(actualClass)) {
classLoader = this.getClass().getClassLoader();
log(sm.getString
("standardWrapper.containerServlet", getName()));
}
// Load the specified servlet class from the appropriate class loader
Class classClass = null;
try {
//加载 Servlet 对象的类到jvm
if (classLoader != null) {
System.out.println("Using classLoader.loadClass");
classClass = classLoader.loadClass(actualClass);
} else {
System.out.println("Using forName");
classClass = Class.forName(actualClass);
}
} catch (ClassNotFoundException e) {
unavailable(null);
throw new ServletException
(sm.getString("standardWrapper.missingClass", actualClass),
e);
}
if (classClass == null) {
unavailable(null);
throw new ServletException
(sm.getString("standardWrapper.missingClass", actualClass));
}
// Instantiate and initialize an instance of the servlet class itself
try {
//通过反射实例化 Servlet 对象
servlet = (Servlet) classClass.newInstance();
} catch (ClassCastException e) {
unavailable(null);
// Restore the context ClassLoader
throw new ServletException
(sm.getString("standardWrapper.notServlet", actualClass), e);
} catch (Throwable e) {
unavailable(null);
// Restore the context ClassLoader
throw new ServletException
(sm.getString("standardWrapper.instantiate", actualClass), e);
}
// Check if loading the servlet in this web application should be
// allowed
if (!isServletAllowed(servlet)) {
throw new SecurityException
(sm.getString("standardWrapper.privilegedServlet",
actualClass));
}
// Special handling for ContainerServlet instances
if ((servlet instanceof ContainerServlet) &&
isContainerProvidedServlet(actualClass)) {
System.out.println("calling setWrapper");
((ContainerServlet) servlet).setWrapper(this);
System.out.println("after calling setWrapper");
}
// Call the initialization method of this servlet
try {
//发送事件
instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
servlet);
//调用 Servlet 的init方法
servlet.init(facade);
// Invoke jspInit on JSP pages
if ((loadOnStartup > 0) && (jspFile != null)) {
// Invoking jspInit
HttpRequestBase req = new HttpRequestBase();
HttpResponseBase res = new HttpResponseBase();
req.setServletPath(jspFile);
req.setQueryString("jsp_precompile=true");
servlet.service(req, res);
}
instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
servlet);
} catch (UnavailableException f) {
instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
servlet, f);
unavailable(f);
throw f;
} catch (ServletException f) {
instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
servlet, f);
// If the servlet wanted to be unavailable it would have
// said so, so do not call unavailable(null).
throw f;
} catch (Throwable f) {
instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
servlet, f);
// If the servlet wanted to be unavailable it would have
// said so, so do not call unavailable(null).
throw new ServletException
(sm.getString("standardWrapper.initException", getName()), f);
}
// Register our newly initialized instance
//如果当前 Servlet 实现了 SingleThreadModel 接口,加入对象池中
singleThreadModel = servlet instanceof SingleThreadModel;
if (singleThreadModel) {
if (instancePool == null)
instancePool = new Stack();
}
fireContainerEvent("load", this);
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
if (getServletContext() != null) {
getServletContext().log(log);
} else {
out.println(log);
}
}
}
//返回创建的 Servlet 对象
return servlet;
}
StandedWrapperValve 的 createFilterChain方法
private ApplicationFilterChain createFilterChain(Request request,
Servlet servlet) {
if (servlet == null)
return (null);
// 创建并且初始化一个过滤链对象ApplicationFilterChain
ApplicationFilterChain filterChain = new ApplicationFilterChain();
filterChain.setServlet(servlet);
StandardWrapper wrapper = (StandardWrapper) getContainer();
filterChain.setSupport(wrapper.getInstanceSupport());
// 获取Context的过滤mappings
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();
if ((filterMaps == null) || (filterMaps.length == 0))
return (filterChain);
// 获取我们需要的匹配 fliter mappings 的信息
String requestPath = null;
if (request instanceof HttpRequest) {
HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
String contextPath = hreq.getContextPath(); //设置的一个context对用的mapper匹配路径
if (contextPath == null) {
contextPath = "";
}
String requestURI = ((HttpRequest) request).getDecodedRequestURI();
//去掉RequestURI中的contextPath
if (requestURI.length() >= contextPath.length()) {
requestPath = requestURI.substring(contextPath.length());
}
}
String servletName = wrapper.getName();
int n = 0;
// 根据RequestURI匹配FilterMaps中的过滤项,添加到filterChain中
for (int i = 0; i < filterMaps.length; i++) {
if (!matchFiltersURL(filterMaps[i], requestPath))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
continue;
}
filterChain.addFilter(filterConfig);
n++;
}
// 根据StanderWrapper的Name来匹配FilterMaps中的过滤项,添加到filterChain
for (int i = 0; i < filterMaps.length; i++) {
if (!matchFiltersServlet(filterMaps[i], servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
continue;
}
filterChain.addFilter(filterConfig);
n++;
}
return (filterChain);
}
使用过滤链过滤Request与Response:filterChain.doFilter(sreq, sres);
这里是调用ApplicationFilterChain的doFilter()方法,doFilter内部有调用了 internalDoFilter()方法。下面是internalDoFilter方法的实现:
作者:mecury
链接:https://www.jianshu.com/p/e6a98cab6b72
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
/*
* 此源代码摘自Tomcat版本 8.5.23
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
* Implementation of javax.servlet.FilterChain used to manage
* the execution of a set of filters for a particular request. When the
* set of defined filters has all been executed, the next call to
* doFilter() will execute the servlet's service()
* method itself.
*
* @author Craig R. McClanahan
*/
public final class ApplicationFilterChain implements FilterChain {
// Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
static {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest = new ThreadLocal<>();
lastServicedResponse = new ThreadLocal<>();
} else {
lastServicedRequest = null;
lastServicedResponse = null;
}
}
// -------------------------------------------------------------- Constants
public static final int INCREMENT = 10;
// ----------------------------------------------------- Instance Variables
/**
* Filters. 执行目标Servlet.service()方法前需要经历的过滤器Filter,初始化为0个元素的数组对象
*/
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
/**
* The int which is used to maintain the current position
* in the filter chain.
* 用于记录过滤器链中当前所执行的过滤器的位置,是当前过滤器在filters数组的下标,初始化为0
*/
private int pos = 0;
/**
* The int which gives the current number of filters in the chain.
* 过滤器链中过滤器的个数(注意:并不是数组filters的长度),初始化为0,和filters数组的初始长度一致
*/
private int n = 0;
/**
* The servlet instance to be executed by this chain.
* 该过滤器链执行完过滤器后最终要执行的目标Servlet
*/
private Servlet servlet = null;
/**
* Does the associated servlet instance support async processing?
* 所关联的Servlet实例是否支持异步处理 ? 缺省为 false,表示缺省情况下不支持异步处理。
*/
private boolean servletSupportsAsync = false;
/**
* The string manager for our package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Static class array used when the SecurityManager is turned on and
* <code>doFilter</code> is invoked.
*/
private static final Class<?>[] classType = new Class[]{
ServletRequest.class, ServletResponse.class, FilterChain.class};
/**
* Static class array used when the SecurityManager is turned on and
* <code>service</code> is invoked.
*/
private static final Class<?>[] classTypeUsedInService = new Class[]{
ServletRequest.class, ServletResponse.class};
// ---------------------------------------------------- FilterChain Methods
/**
* Invoke the next filter in this chain, passing the specified request
* and response. If there are no more filters in this chain, invoke
* the service() method of the servlet itself.
* 执行过滤器链中的下一个过滤器Filter。如果链中所有过滤器都执行过,
* 则调用servlet的service()方法。
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet exception occurs
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// 下面的if-else分支主要是根据Globals.IS_SECURITY_ENABLED是true还是false决定
// 如何调用目标逻辑,但两种情况下,目标逻辑最终都是 internalDoFilter(req,res)
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) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
// 找到目标 Filter 对象
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
// 执行目标 Filter 对象的 doFilter方法,
// 注意,这里当前ApplicationFilterChain对象被传递到了目标
// Filter对象的doFilter方法,而目标Filter对象的doFilter在执行完自己
// 被指定的逻辑之后会反过来调用这个ApplicationFilterChain对象的
// doFilter方法,只是pos向前推进了一个过滤器。这个ApplicationFilterChain
// 和Filter之间反复调用彼此doFilter方法的过程一直持续直到当前链发现所有的
// Filter都已经被执行
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
// 这里是过滤器链中所有的过滤器都已经被执行的情况,现在需要调用servlet实例本身了。
// !!! 注意 : 虽然这里开始调用servlet实例了,但是从当前方法执行堆栈可以看出,过滤器链
// 和链中过滤器的doFilter方法的执行帧还在堆栈中并未退出,他们会在servlet实例的逻辑
// 执行完后,分别执行完自己剩余的的逻辑才会逐一结束。
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);
}
}
}
/**
* The last request passed to a servlet for servicing from the current
* thread.
*
* @return The last request to be serviced.
*/
public static ServletRequest getLastServicedRequest() {
return lastServicedRequest.get();
}
/**
* The last response passed to a servlet for servicing from the current
* thread.
*
* @return The last response to be serviced.
*/
public static ServletResponse getLastServicedResponse() {
return lastServicedResponse.get();
}
// -------------------------------------------------------- Package Methods
/**
* Add a filter to the set of filters that will be executed in this chain.
* 往当前要执行的过滤器链的过滤器集合filters中增加一个过滤器
* @param filterConfig The FilterConfig for the servlet to be executed
*/
void addFilter(ApplicationFilterConfig filterConfig) {
// Prevent the same filter being added multiple times
// 去重处理,如果已经添加进来则避免二次添加
for(ApplicationFilterConfig filter:filters)
if(filter==filterConfig)
return;
if (n == filters.length) {
// !!! 请注意:每次需要扩容时并不是增加一个元素空间,而是增加INCREMENT个,
// 这个行为的结果是filters数组的长度和数组中过滤器的个数n并不相等
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
/**
* Release references to the filters and wrapper executed by this chain.
*/
void release() {
for (int i = 0; i < n; i++) {
filters[i] = null;
}
n = 0;
pos = 0;
servlet = null;
servletSupportsAsync = false;
}
/**
* Prepare for reuse of the filters and wrapper executed by this chain.
*/
void reuse() {
pos = 0;
}
/**
* Set the servlet that will be executed at the end of this chain.
*
* @param servlet The Wrapper for the servlet to be executed
*/
void setServlet(Servlet servlet) {
this.servlet = servlet;
}
void setServletSupportsAsync(boolean servletSupportsAsync) {
this.servletSupportsAsync = servletSupportsAsync;
}
/**
* Identifies the Filters, if any, in this FilterChain that do not support
* async.
*
* @param result The Set to which the fully qualified class names of each
* Filter in this FilterChain that does not support async will
* be added
*/
public void findNonAsyncFilters(Set<String> result) {
for (int i = 0; i < n ; i++) {
ApplicationFilterConfig filter = filters[i];
if ("false".equalsIgnoreCase(filter.getFilterDef().getAsyncSupported())) {
result.add(filter.getFilterClass());
}
}
}
}
释放servlet,释放的STM类型的servlet会被放入的stack中,以后会被再次使用:deallocate(Servlet servlet)
public void deallocate(Servlet servlet) throws ServletException {
//如果不是STM,就直接返回。STM类型的Servlet每次只有一个Servelt在执行Service方法
if (!singleThreadModel) {
countAllocated--;
return;
}
// 如果是STM,就放入到实例池中,以备后来使用
synchronized (instancePool) {
countAllocated--;
instancePool.push(servlet);
instancePool.notify();
}
}