q528 发表于 2017-1-28 15:29:59

tomcat源码解析--StandardWrapperValve

  StandardWrapperValve wrapper的最后一个valve,进入servlet之前的最后一步
  invoke方法
  先判断context和wrapper的 是否可用

if (!context.getAvailable()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardContext.isUnavailable"));
unavailable = true;
}
// Check for the servlet being marked unavailable
if (!unavailable && wrapper.isUnavailable()) {
container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
unavailable = true;
}
  加载servlet

if (!unavailable) {
servlet = wrapper.allocate();
}
  allocate方法

   boolean newInstance = false;
// 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 {
if (log.isDebugEnabled())
log.debug("Allocating non-STM instance");
instance = loadServlet();
// For non-STM, increment here to prevent a race
// condition with unload. Bug 43683, test case #3
if (!singleThreadModel) {
newInstance = true;
countAllocated.incrementAndGet();
}
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException
(sm.getString("standardWrapper.allocate"), e);
}
}
}
}
  loadServlet 方法
  1. 对于JSP 的处理

String actualClass = servletClass;
if ((actualClass == null) && (jspFile != null)) {
Wrapper jspWrapper = (Wrapper)
((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
if (jspWrapper != null) {
actualClass = jspWrapper.getServletClass();
// Merge init parameters
String paramNames[] = jspWrapper.findInitParameters();
for (int i = 0; i < paramNames.length; i++) {
if (parameters.get(paramNames) == null) {
parameters.put
(paramNames,
jspWrapper.findInitParameter(paramNames));
}
}
}
  设置classloader,默认为loader的classloader,如果是 ContainerServlet 的子类或者 org.apache.catalina包下的,则设置当前的classloader

ClassLoader classLoader = loader.getClassLoader();
// Special case class loader for a container provided servlet
//
if (isContainerProvidedServlet(actualClass) &&
! ((Context)getParent()).getPrivileged() ) {
// If it is a priviledged context - using its own
// class loader will work, since it's a child of the container
// loader
classLoader = this.getClass().getClassLoader();
}
  加载servlet class,如果是包限制的,则特殊处理

if (SecurityUtil.isPackageProtectionEnabled()){
final ClassLoader fclassLoader = classLoader;
final String factualClass = actualClass;
try{
classClass = (Class)AccessController.doPrivileged(
new PrivilegedExceptionAction(){
public Object run() throws Exception{
if (fclassLoader != null) {
return fclassLoader.loadClass(factualClass);
} else {
return Class.forName(factualClass);
}
}
});
} catch(PrivilegedActionException pax){
Exception ex = pax.getException();
if (ex instanceof ClassNotFoundException){
throw (ClassNotFoundException)ex;
} else {
getServletContext().log( "Error loading "
+ fclassLoader + " " + factualClass, ex );
}
}
} else {
if (classLoader != null) {
classClass = classLoader.loadClass(actualClass);
} else {
classClass = Class.forName(actualClass);
}
}
  创建servlet 实例,处理注解(StandardContext的AnnotationProcessor??)

servlet = (Servlet) classClass.newInstance();
// Annotation processing
if (!((Context) getParent()).getIgnoreAnnotations()) {
if (getParent() instanceof StandardContext) {
((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet);
((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet);
}
}
  触发 before_init_event

instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
servlet);
  servlet init方法调用,对于设置SecurityManager的特殊对待(SecurityUtil???)

                if( Globals.IS_SECURITY_ENABLED) {
boolean success = false;
try {
Object[] args = new Object[]{ facade };
SecurityUtil.doAsPrivilege("init",
servlet,
classType,
args);
success = true;
} finally {
if (!success) {
// destroy() will not be called, thus clear the reference now
SecurityUtil.remove(servlet);
}
}
} else {
servlet.init(facade);
}
  JSP 处理,直接调用service了

if ((loadOnStartup >= 0) && (jspFile != null)) {
// Invoking jspInit
DummyRequest req = new DummyRequest();
req.setServletPath(jspFile);
req.setQueryString(Constants.PRECOMPILE + "=true");
DummyResponse res = new DummyResponse();
if( Globals.IS_SECURITY_ENABLED) {
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args);
args = null;
} else {
servlet.service(req, res);
}
}
  并且还会判断servlet是否 SingleThreadModel 子类,如果是会创建相关的instancePool

singleThreadModel = servlet instanceof SingleThreadModel;
if (singleThreadModel) {
if (instancePool == null)
instancePool = new Stack();
}
  触发load事件

fireContainerEvent("load", this);
  对于非多线程的servlet,池的处理

synchronized (instancePool) {
while (countAllocated.get() >= nInstances) {
// Allocate a new instance if possible, or else wait
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException
(sm.getString("standardWrapper.allocate"), e);
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
;
}
}
}
if (log.isTraceEnabled())
log.trace("Returning allocated STM instance");
countAllocated.incrementAndGet();
return (Servlet) instancePool.pop();
}
  allocate 结束
  获取过滤器链

ApplicationFilterFactory factory =
ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain =
factory.createFilterChain(request, wrapper, servlet);
  过滤器处理

if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (comet) {
filterChain.doFilterEvent(request.getEvent());
request.setComet(true);
} else {
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (comet) {
request.setComet(true);
filterChain.doFilterEvent(request.getEvent());
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
  ApplicationFilterChain.doFilter方法调用internalDoFilter方法处理
  filter 遍历处理

ApplicationFilterConfig filterConfig = filters;
Filter filter = null;
try {
filter = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
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);
args = null;
} else {
filter.doFilter(request, response, this);
}
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
  service 方法调用

support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
servlet, request, response);
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
if( 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);   
args = null;
} else {
servlet.service((HttpServletRequest) request,
(HttpServletResponse) response);
}
} else {
servlet.service(request, response);
}
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);
  调用结束,开始善后
  过滤器标志回滚

if (filterChain != null) {
if (request.isComet()) {
// If this is a Comet request, then the same chain will be used for the
// processing of all subsequent events.
filterChain.reuse();
} else {
filterChain.release();
}
}
  如果有servlet 池,释放当前servlet

if (servlet != null) {
wrapper.deallocate(servlet);
}
  释放当前servlet在 wrapper中

if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
页: [1]
查看完整版本: tomcat源码解析--StandardWrapperValve